mirror of
https://github.com/penpot/penpot.git
synced 2025-03-20 19:51:23 -05:00
Refactor shapes attributes handling.
This commit is contained in:
parent
b3d995de53
commit
28d18a07a0
14 changed files with 440 additions and 543 deletions
|
@ -90,18 +90,6 @@
|
|||
(rx/map (fn [{:keys [x y] :as pt}]
|
||||
(apply-temporal-displacement id (gpt/subtract pt point1)))))))))
|
||||
|
||||
(defn update-line-attrs
|
||||
[sid {:keys [x1 y1 x2 y2] :as opts}]
|
||||
(reify
|
||||
udp/IPageUpdate
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [shape (get-in state [:shapes sid])
|
||||
props (select-keys opts [:x1 :y1 :x2 :y2])
|
||||
props' (select-keys shape [:x1 :y1 :x2 :y2])]
|
||||
(update-in state [:shapes sid] geom/setup
|
||||
(merge props' props))))))
|
||||
|
||||
(defn update-rotation
|
||||
[sid rotation]
|
||||
{:pre [(number? rotation)
|
||||
|
@ -236,57 +224,68 @@
|
|||
(update [_ state]
|
||||
(assoc-in state [:shapes sid :content] content))))
|
||||
|
||||
(defn update-fill-attrs
|
||||
[sid {:keys [color opacity] :as opts}]
|
||||
(reify
|
||||
udp/IPageUpdate
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:shapes sid]
|
||||
merge
|
||||
(when color {:fill color})
|
||||
(when opacity {:fill-opacity opacity})))))
|
||||
;; --- Update Shape Attrs
|
||||
|
||||
(defn update-font-attrs
|
||||
[sid {:keys [family style weight size align
|
||||
letter-spacing line-height] :as opts}]
|
||||
(reify
|
||||
udp/IPageUpdate
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:shapes sid :font]
|
||||
merge
|
||||
(when line-height {:line-height line-height})
|
||||
(when letter-spacing {:letter-spacing letter-spacing})
|
||||
(when align {:align align})
|
||||
(when family {:family family})
|
||||
(when style {:style style})
|
||||
(when weight {:weight weight})
|
||||
(when size {:size size})))))
|
||||
(declare UpdateAttrs)
|
||||
|
||||
(defn update-stroke-attrs
|
||||
[sid {:keys [color opacity type width] :as opts}]
|
||||
(reify
|
||||
udp/IPageUpdate
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:shapes sid]
|
||||
merge
|
||||
(when type {:stroke-type type})
|
||||
(when width {:stroke-width width})
|
||||
(when color {:stroke color})
|
||||
(when opacity {:stroke-opacity opacity})))))
|
||||
(deftype UpdateAttrs [id attrs]
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(println "update-attrs" id attrs)
|
||||
(let [{:keys [type] :as shape} (get-in state [:shapes id])]
|
||||
(if (= type :group)
|
||||
(rx/from-coll (map #(UpdateAttrs. % attrs) (:items shape)))
|
||||
(rx/of #(update-in % [:shapes id] merge attrs))))))
|
||||
|
||||
(defn update-radius-attrs
|
||||
[sid {:keys [rx ry] :as opts}]
|
||||
(reify
|
||||
udp/IPageUpdate
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:shapes sid]
|
||||
merge
|
||||
(when rx {:rx rx})
|
||||
(when ry {:ry ry})))))
|
||||
(s/def ::fill-color us/color?)
|
||||
(s/def ::fill-opacity number?)
|
||||
(s/def ::line-height number?)
|
||||
(s/def ::letter-spacing number?)
|
||||
(s/def ::text-align #{"left" "right" "center" "justify"})
|
||||
(s/def ::font-family string?)
|
||||
(s/def ::font-style string?)
|
||||
(s/def ::font-weight string?)
|
||||
(s/def ::font-size number?)
|
||||
(s/def ::stroke-style #{:none :solid :dotted :dashed :mixed})
|
||||
(s/def ::stroke-width number?)
|
||||
(s/def ::stroke-color us/color?)
|
||||
(s/def ::stroke-opacity number?)
|
||||
(s/def ::rx number?)
|
||||
(s/def ::ry number?)
|
||||
(s/def ::proportion number?)
|
||||
(s/def ::proportion-lock boolean?)
|
||||
(s/def ::collapsed boolean?)
|
||||
(s/def ::hidden boolean?)
|
||||
(s/def ::blocked boolean?)
|
||||
(s/def ::locked boolean?)
|
||||
|
||||
(s/def ::shape-attrs
|
||||
(s/keys :opt-un [::fill-color
|
||||
::fill-opacity
|
||||
::line-height
|
||||
::letter-spacing
|
||||
::text-align
|
||||
::font-family
|
||||
::font-style
|
||||
::font-weight
|
||||
::font-size
|
||||
::stroke-style
|
||||
::stroke-width
|
||||
::stroke-color
|
||||
::stroke-opacity
|
||||
::rx ::ry
|
||||
::proportion-lock
|
||||
::proportion
|
||||
::collapsed
|
||||
::hidden
|
||||
::blocked
|
||||
::locked]))
|
||||
|
||||
(defn update-attrs
|
||||
[id attrs]
|
||||
{:pre [(uuid? id) (us/valid? ::shape-attrs attrs)]}
|
||||
(let [atts (us/extract attrs ::shape-attrs)]
|
||||
(UpdateAttrs. id attrs)))
|
||||
|
||||
;; --- Shape Proportions
|
||||
|
||||
|
@ -629,27 +628,16 @@
|
|||
(rx/from-coll
|
||||
(into [(deselect-all)] (map #(delete-shape %) selected)))))))
|
||||
|
||||
(defn update-selected-shapes-fill
|
||||
"Update the fill related attributed on
|
||||
selected shapes."
|
||||
[opts]
|
||||
(reify
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(->> (get-in state [:workspace :selected])
|
||||
(map #(update-fill-attrs % opts))
|
||||
(rx/from-coll)))))
|
||||
(deftype UpdateSelectedShapesAttrs [attrs]
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [xf (map #(update-attrs % attrs))]
|
||||
(rx/from-coll (sequence xf (get-in state [:workspace :selected]))))))
|
||||
|
||||
(defn update-selected-shapes-stroke
|
||||
"Update the fill related attributed on
|
||||
selected shapes."
|
||||
[opts]
|
||||
(reify
|
||||
ptk/WatchEvent
|
||||
(watch [_ state s]
|
||||
(rx/from-coll
|
||||
(->> (get-in state [:workspace :selected])
|
||||
(map #(update-stroke-attrs % opts)))))))
|
||||
(defn update-selected-shapes-attrs
|
||||
[attrs]
|
||||
{:pre [(us/valid? ::shape-attrs attrs)]}
|
||||
(UpdateSelectedShapesAttrs. attrs))
|
||||
|
||||
;; --- Move Selected Layer
|
||||
|
||||
|
|
|
@ -2,47 +2,55 @@
|
|||
;; 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 <niwi@niwi.nz>
|
||||
;; Copyright (c) 2016-2017 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns uxbox.main.ui.shapes.attrs)
|
||||
|
||||
(def ^:private +style-attrs+
|
||||
#{:fill :fill-opacity :opacity
|
||||
:stroke :stroke-opacity :stroke-width
|
||||
:stroke-type :rx :ry})
|
||||
(def shape-style-attrs
|
||||
#{:fill-color
|
||||
:fill-opacity
|
||||
:stroke-color
|
||||
:stroke-opacity
|
||||
:stroke-width
|
||||
:stroke-style
|
||||
:rx
|
||||
:ry})
|
||||
|
||||
(defn- transform-stroke-type
|
||||
(def shape-default-attrs
|
||||
{:stroke-color "#000000"
|
||||
:stroke-opacity 1
|
||||
:fill-color "#000000"
|
||||
:fill-opacity 1})
|
||||
|
||||
(defn- stroke-type->dasharray
|
||||
[style]
|
||||
(case style
|
||||
:mixed "5,5,1,5"
|
||||
:dotted "5,5"
|
||||
:dashed "10,10"))
|
||||
|
||||
(defn- rename-attr
|
||||
[[key value :as pair]]
|
||||
(case key
|
||||
:stroke-color [:stroke value]
|
||||
:fill-color [:fill value]
|
||||
pair))
|
||||
|
||||
(defn- rename-attrs
|
||||
[attrs]
|
||||
(if-let [type (:stroke-type attrs)]
|
||||
(let [value (case type
|
||||
:mixed "5,5,1,5"
|
||||
:dotted "5,5"
|
||||
:dashed "10,10"
|
||||
nil)]
|
||||
(if value
|
||||
(-> attrs
|
||||
(assoc! :stroke-dasharray value)
|
||||
(dissoc! :stroke-type))
|
||||
(dissoc! attrs :stroke-type)))
|
||||
attrs))
|
||||
(into {} (map rename-attr) attrs))
|
||||
|
||||
(defn- transform-stroke-attrs
|
||||
[attrs]
|
||||
(if (= (:stroke-type attrs :none) :none)
|
||||
(dissoc! attrs :stroke-type :stroke-width :stroke-opacity :stroke)
|
||||
(transform-stroke-type attrs)))
|
||||
[{:keys [stroke-style] :or {stroke-style :none} :as attrs}]
|
||||
(if (= stroke-style :none)
|
||||
(dissoc attrs :stroke-style :stroke-width :stroke-opacity :stroke-color)
|
||||
(-> (merge shape-default-attrs attrs)
|
||||
(assoc :stroke-dasharray (stroke-type->dasharray stroke-style))
|
||||
(dissoc :stroke-style))))
|
||||
|
||||
(defn- extract-style-attrs
|
||||
"Extract predefinet attrs from shapes."
|
||||
[shape]
|
||||
(let [attrs (select-keys shape +style-attrs+)]
|
||||
(-> (transient attrs)
|
||||
(transform-stroke-attrs)
|
||||
(persistent!))))
|
||||
|
||||
(defn- make-debug-attrs
|
||||
[shape]
|
||||
(let [attrs (select-keys shape [:rotation :width :height :x :y])
|
||||
xf (map (fn [[x v]]
|
||||
[(keyword (str "data-" (name x))) v]))]
|
||||
(into {} xf attrs)))
|
||||
(-> (select-keys shape shape-style-attrs)
|
||||
(transform-stroke-attrs)
|
||||
(rename-attrs)))
|
||||
|
|
|
@ -69,9 +69,7 @@
|
|||
(let [xfmt (cond-> (or tmp-resize-xform (gmt/matrix))
|
||||
tmp-displacement (gmt/translate tmp-displacement))
|
||||
|
||||
props {:id (str id) :transform (str xfmt)}
|
||||
|
||||
attrs (merge props (attrs/extract-style-attrs shape))]
|
||||
attrs {:id (str id) :transform (str xfmt)}]
|
||||
[:g attrs
|
||||
(for [item (reverse items)
|
||||
:let [key (str item)]]
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
;; --- Rect Shape
|
||||
|
||||
(defn- rotate
|
||||
;; TODO: revisit, i'm not sure if this function is duplicated.
|
||||
[mt {:keys [x1 y1 x2 y2 width height rotation] :as shape}]
|
||||
(let [x-center (+ x1 (/ width 2))
|
||||
y-center (+ y1 (/ height 2))
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
;; --- Text Component
|
||||
|
||||
(declare text-shape)
|
||||
(declare text-shape-wrapper)
|
||||
(declare text-shape-edit)
|
||||
|
||||
(mx/defcs text-component
|
||||
|
@ -55,7 +56,7 @@
|
|||
:on-mouse-down on-mouse-down}
|
||||
(if edition?
|
||||
(text-shape-edit shape)
|
||||
(text-shape shape))])))
|
||||
(text-shape-wrapper shape))])))
|
||||
|
||||
;; --- Text Styles Helpers
|
||||
|
||||
|
@ -66,28 +67,36 @@
|
|||
:stroke-opacity "0.4"}})
|
||||
|
||||
(defn- make-style
|
||||
[{:keys [font fill opacity]
|
||||
:or {fill "#000000" opacity 1}}]
|
||||
(let [{:keys [family weight style size align
|
||||
line-height letter-spacing]
|
||||
:or {family "sourcesanspro"
|
||||
weight "normal"
|
||||
style "normal"
|
||||
line-height 1.4
|
||||
letter-spacing 1
|
||||
align "left"
|
||||
size 16}} font
|
||||
color (-> fill
|
||||
(color/hex->rgba opacity)
|
||||
[{:keys [fill-color
|
||||
fill-opacity
|
||||
font-family
|
||||
font-weight
|
||||
font-style
|
||||
font-size
|
||||
text-align
|
||||
line-height
|
||||
letter-spacing]
|
||||
:or {fill-color "#000000"
|
||||
fill-opacity 1
|
||||
font-family "sourcesanspro"
|
||||
font-weight "normal"
|
||||
font-style "normal"
|
||||
fobt-size 16
|
||||
line-height 1.4
|
||||
letter-spacing 1
|
||||
text-align "left"}
|
||||
:as shape}]
|
||||
(let [color (-> fill-color
|
||||
(color/hex->rgba fill-opacity)
|
||||
(color/rgb->str))]
|
||||
(merge
|
||||
{:fontSize (str size "px")
|
||||
:color color
|
||||
:whiteSpace "pre"
|
||||
:textAlign align
|
||||
:fontFamily family
|
||||
:fontWeight weight
|
||||
:fontStyle style}
|
||||
{:fontSize (str font-size "px")
|
||||
:color fill-color
|
||||
:whiteSpace "pre-wrap"
|
||||
:textAlign text-align
|
||||
:fontFamily font-family
|
||||
:fontWeight font-weight
|
||||
:fontStyle font-style}
|
||||
(when line-height {:lineHeight line-height})
|
||||
(when letter-spacing {:letterSpacing letter-spacing}))))
|
||||
|
||||
|
@ -105,11 +114,9 @@
|
|||
{:did-mount text-shape-edit-did-mount
|
||||
:mixins [mx/static]}
|
||||
[{:keys [id x1 y1 content] :as shape}]
|
||||
(let [size (geom/size shape)
|
||||
(let [{:keys [width height]} (geom/size shape)
|
||||
style (make-style shape)
|
||||
;; rfm (geom/transformation-matrix shape)
|
||||
props {:x x1 :y y1} ;; :transform (str rfm)}
|
||||
props (merge props size)]
|
||||
props {:x x1 :y y1 :width width :height height}]
|
||||
(letfn [#_(on-blur [ev]
|
||||
(rlocks/release! :ui/text-edit)
|
||||
(on-done))
|
||||
|
@ -117,15 +124,15 @@
|
|||
(let [content (dom/event->inner-text ev)]
|
||||
(st/emit! (uds/update-text id {:content content}))))]
|
||||
[:g
|
||||
[:rect (merge props +select-rect-attrs+)]
|
||||
#_[:rect (merge props +select-rect-attrs+)]
|
||||
[:foreignObject props
|
||||
[:p {:ref "container"
|
||||
;; :on-blur on-blur
|
||||
:on-input on-input
|
||||
:contentEditable true
|
||||
:style style}]]])))
|
||||
[:div {:style style}
|
||||
[:p {:ref "container"
|
||||
;; :on-blur on-blur
|
||||
:on-input on-input
|
||||
:contentEditable true}]]]])))
|
||||
|
||||
;; --- Text Shape
|
||||
;; --- Text Shape Wrapper
|
||||
|
||||
;; NOTE: this is a hack for the browser rendering.
|
||||
;;
|
||||
|
@ -135,30 +142,46 @@
|
|||
;; completelly invisible. The complete dom rerender fixes that
|
||||
;; problem.
|
||||
|
||||
(defn- text-shape-did-update
|
||||
(defn text-shape-wrapper-did-mount
|
||||
[own]
|
||||
(let [pref (mx/ref-node own "fo")
|
||||
html (.-innerHTML pref)]
|
||||
(set! (.-innerHTML pref) html)
|
||||
(let [[shape] (:rum/args own)
|
||||
dom (mx/ref-node own "fobject")
|
||||
html (mx/render-static-html (text-shape shape))]
|
||||
(set! (.-innerHTML dom) html))
|
||||
own)
|
||||
|
||||
(defn text-shape-wrapper-did-remount
|
||||
[old own]
|
||||
(let [[old-shape] (:rum/args old)
|
||||
[shape] (:rum/args own)]
|
||||
(when (not= shape old-shape)
|
||||
(let [dom (mx/ref-node own "fobject")
|
||||
html (mx/render-static-html (text-shape shape))]
|
||||
(set! (.-innerHTML dom) html)))
|
||||
own))
|
||||
|
||||
(mx/defc text-shape
|
||||
(mx/defc text-shape-wrapper
|
||||
{:mixins [mx/static]
|
||||
:did-update text-shape-did-update}
|
||||
[{:keys [tmp-resize-xform] :as shape}]
|
||||
(let [shape (cond-> (geom/size shape)
|
||||
tmp-resize-xform (geom/transform shape tmp-resize-xform))
|
||||
:did-mount text-shape-wrapper-did-mount
|
||||
:did-remount text-shape-wrapper-did-remount}
|
||||
[{:keys [id tmp-resize-xform tmp-displacement] :as shape}]
|
||||
(let [xfmt (cond-> (gmt/matrix)
|
||||
tmp-displacement (gmt/translate tmp-displacement)
|
||||
tmp-resize-xform (gmt/multiply tmp-resize-xform))
|
||||
|
||||
{:keys [id x1 y1 content
|
||||
width height
|
||||
tmp-displacement]} (geom/size shape)
|
||||
{:keys [x1 y1 width height] :as shape} (-> (geom/transform shape xfmt)
|
||||
(geom/size))]
|
||||
[:foreignObject {:x x1
|
||||
:y y1
|
||||
:id (str id)
|
||||
:ref "fobject"
|
||||
:width width
|
||||
:height height}]))
|
||||
|
||||
xfmt (cond-> (gmt/matrix)
|
||||
tmp-displacement (gmt/translate tmp-displacement))
|
||||
;; --- Text Shape
|
||||
|
||||
style (make-style shape)
|
||||
props {:x x1 :y y1 :id (str id) :ref "fo"
|
||||
:width width :height height
|
||||
:transform (str xfmt)}]
|
||||
[:foreignObject props
|
||||
[:p {:ref "p" :style style} content]]))
|
||||
(mx/defc text-shape
|
||||
[{:keys [content] :as shape}]
|
||||
(let [style (make-style shape)]
|
||||
[:div {:style style}
|
||||
[:p content]]))
|
||||
|
|
|
@ -33,10 +33,10 @@
|
|||
{:mixins [mx/static]}
|
||||
[color]
|
||||
(letfn [(select-color [event]
|
||||
(dom/prevent-default event)
|
||||
(if (kbd/shift? event)
|
||||
(st/emit! (uds/update-selected-shapes-stroke {:color color}))
|
||||
(st/emit! (uds/update-selected-shapes-fill {:color color}))))]
|
||||
(let [attrs (if (kbd/shift? event)
|
||||
{:stroke-color color}
|
||||
{:fill-color color})]
|
||||
(st/emit! (uds/update-selected-shapes-attrs attrs))))]
|
||||
(let [rgb-vec (hex->rgb color)
|
||||
rgb-color (apply str "" (interpose ", " rgb-vec))]
|
||||
[:div.color-cell {:key (str color)
|
||||
|
|
|
@ -32,15 +32,11 @@
|
|||
(mx/defcs shape-colorpicker
|
||||
{:mixins [mx/reactive mx/static]}
|
||||
[own {:keys [x y shape attr] :as opts}]
|
||||
(let [shape (mx/react (focus-shape shape))
|
||||
(let [{:keys [id] :as shape} (mx/react (focus-shape shape))
|
||||
left (- x 260)
|
||||
top (- y 50)]
|
||||
(letfn [(change-color [color]
|
||||
(let [attrs {:color color}]
|
||||
(st/emit!
|
||||
(case attr
|
||||
:stroke (uds/update-stroke-attrs (:id shape) attrs)
|
||||
:fill (uds/update-fill-attrs (:id shape) attrs)))))]
|
||||
(st/emit! (uds/update-attrs id {attr color})))]
|
||||
[:div.colorpicker-tooltip
|
||||
{:style {:left (str left "px")
|
||||
:top (str top "px")}}
|
||||
|
|
|
@ -16,11 +16,10 @@
|
|||
[uxbox.main.data.shapes :as uds]
|
||||
[uxbox.main.ui.workspace.base :as wb]
|
||||
[uxbox.main.ui.icons :as i]
|
||||
[uxbox.util.mixins :as mx :include-macros true]
|
||||
[uxbox.main.ui.shapes.attrs :refer [shape-default-attrs]]
|
||||
[uxbox.main.ui.workspace.sidebar.options.icon-measures :as options-iconm]
|
||||
[uxbox.main.ui.workspace.sidebar.options.circle-measures :as options-circlem]
|
||||
[uxbox.main.ui.workspace.sidebar.options.rect-measures :as options-rectm]
|
||||
[uxbox.main.ui.workspace.sidebar.options.line-measures :as options-linem]
|
||||
[uxbox.main.ui.workspace.sidebar.options.fill :as options-fill]
|
||||
[uxbox.main.ui.workspace.sidebar.options.text :as options-text]
|
||||
[uxbox.main.ui.workspace.sidebar.options.stroke :as options-stroke]
|
||||
|
@ -28,19 +27,19 @@
|
|||
[uxbox.main.ui.workspace.sidebar.options.interactions :as options-interactions]
|
||||
[uxbox.main.geom :as geom]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.data :as data]))
|
||||
[uxbox.util.data :as data]
|
||||
[uxbox.util.mixins :as mx :include-macros true]))
|
||||
|
||||
;; --- Constants
|
||||
|
||||
(def ^:private +menus-map+
|
||||
{:icon [::icon-measures ::fill ::stroke ::interactions]
|
||||
:rect [::rect-measures ::fill ::stroke ::interactions]
|
||||
:line [::line-measures ::stroke ::interactions]
|
||||
:path [::fill ::stroke ::interactions]
|
||||
:circle [::circle-measures ::fill ::stroke ::interactions]
|
||||
:text [::fill ::text ::interactions]
|
||||
:image [::interactions]
|
||||
:group [::interactions]
|
||||
:group [::fill ::stroke ::interactions]
|
||||
::page [::page-measures ::page-grid-options]})
|
||||
|
||||
(def ^:private +menus+
|
||||
|
@ -52,10 +51,6 @@
|
|||
:id ::rect-measures
|
||||
:icon i/infocard
|
||||
:comp options-rectm/rect-measures-menu}
|
||||
{:name "Size, position & rotation"
|
||||
:id ::line-measures
|
||||
:icon i/infocard
|
||||
:comp options-linem/line-measures-menu}
|
||||
{:name "Size, position & rotation"
|
||||
:id ::circle-measures
|
||||
:icon i/infocard
|
||||
|
@ -128,7 +123,8 @@
|
|||
(mx/defc options-toolbox
|
||||
{:mixins [mx/static mx/reactive]}
|
||||
[]
|
||||
(let [shape (mx/react selected-shape-ref)
|
||||
(let [shape (->> (mx/react selected-shape-ref)
|
||||
(merge shape-default-attrs))
|
||||
close #(st/emit! (udw/toggle-flag :element-options))]
|
||||
[:div.elementa-options.tool-window
|
||||
[:div.tool-window-bar
|
||||
|
|
|
@ -2,13 +2,11 @@
|
|||
;; 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 <niwi@niwi.nz>
|
||||
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
;; Copyright (c) 2015-2017 Andrey Antukh <niwi@niwi.nz>
|
||||
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.workspace.sidebar.options.fill
|
||||
(:require [sablono.core :as html :refer-macros [html]]
|
||||
[rum.core :as rum]
|
||||
[lentes.core :as l]
|
||||
(:require [lentes.core :as l]
|
||||
[uxbox.util.i18n :refer (tr)]
|
||||
[uxbox.util.router :as r]
|
||||
[potok.core :as ptk]
|
||||
|
@ -21,59 +19,51 @@
|
|||
[uxbox.util.data :refer (parse-int parse-float read-string)]
|
||||
[uxbox.util.spec :refer (color?)]))
|
||||
|
||||
(defn fill-menu-render
|
||||
[own menu shape]
|
||||
(letfn [(change-fill [value]
|
||||
(let [sid (:id shape)]
|
||||
(st/emit! (uds/update-fill-attrs sid value))))
|
||||
(mx/defc fill-menu
|
||||
{:mixins [mx/static]}
|
||||
[menu {:keys [id] :as shape}]
|
||||
(letfn [(change-attrs [attrs]
|
||||
(st/emit! (uds/update-attrs id attrs)))
|
||||
(on-color-change [event]
|
||||
(let [value (dom/event->value event)]
|
||||
(when (color? value)
|
||||
(change-fill {:color value}))))
|
||||
(change-attrs {: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})))
|
||||
(change-attrs {:fill-opacity value})))
|
||||
(on-color-picker-event [color]
|
||||
(change-fill {:color color}))
|
||||
(change-attrs {:fill-color color}))
|
||||
(show-color-picker [event]
|
||||
(let [x (.-clientX event)
|
||||
y (.-clientY event)
|
||||
opts {:x x :y y
|
||||
:shape (:id shape)
|
||||
:attr :fill
|
||||
:attr :fill-color
|
||||
:transparent? true}]
|
||||
(udl/open! :workspace/shape-colorpicker opts)))]
|
||||
[:div.element-set {:key (str (:id menu))}
|
||||
[:div.element-set-title (:name menu)]
|
||||
[:div.element-set-content
|
||||
|
||||
(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-color shape)}
|
||||
:on-click show-color-picker}]
|
||||
[:div.color-info
|
||||
[:input
|
||||
{:on-change on-color-change
|
||||
:value (:fill-color shape)}]]]
|
||||
|
||||
[:span "Color"]
|
||||
[:div.row-flex.color-data
|
||||
[:span.color-th
|
||||
{:style {:background-color (:fill shape "#000000")}
|
||||
:on-click show-color-picker}]
|
||||
[:div.color-info
|
||||
[:input
|
||||
{:on-change on-color-change
|
||||
:value (:fill shape "#000000")}]]]
|
||||
|
||||
;; 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]}))
|
||||
;; SLIDEBAR FOR ROTATION AND OPACITY
|
||||
[:span "Opacity"]
|
||||
[:div.row-flex
|
||||
[:input.slidebar
|
||||
{:type "range"
|
||||
:min "0"
|
||||
:max "10000"
|
||||
:value (* 10000 (:fill-opacity shape))
|
||||
:step "1"
|
||||
:on-change on-opacity-change}]]]]))
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
;; 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 <niwi@niwi.nz>
|
||||
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.workspace.sidebar.options.line-measures
|
||||
(:require [sablono.core :as html :refer-macros [html]]
|
||||
[rum.core :as rum]
|
||||
[lentes.core :as l]
|
||||
[uxbox.util.i18n :refer (tr)]
|
||||
[uxbox.util.router :as r]
|
||||
[potok.core :as ptk]
|
||||
[uxbox.store :as st]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.data.shapes :as uds]
|
||||
[uxbox.main.ui.icons :as i]
|
||||
[uxbox.util.mixins :as mx :include-macros true]
|
||||
[uxbox.main.geom :as geom]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.math :refer (precision-or-0)]
|
||||
[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)]
|
||||
(st/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}]
|
||||
(st/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 (precision-or-0 (:x1 shape 0) 2)
|
||||
:on-change (partial on-pos-change :x1)}]
|
||||
[:input.input-text
|
||||
{:placeholder "y1"
|
||||
:type "number"
|
||||
:value (precision-or-0 (:y1 shape 0) 2)
|
||||
:on-change (partial on-pos-change :y1)}]]
|
||||
|
||||
[:div.row-flex
|
||||
[:input.input-text
|
||||
{:placeholder "x2"
|
||||
:type "number"
|
||||
:value (precision-or-0 (:x2 shape 0) 2)
|
||||
:on-change (partial on-pos-change :x2)}]
|
||||
[:input.input-text
|
||||
{:placeholder "y2"
|
||||
:type "number"
|
||||
:value (precision-or-0 (:y2 shape 0) 2)
|
||||
: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 (precision-or-0 (:rotation shape 0) 2)
|
||||
: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]}))
|
|
@ -2,8 +2,8 @@
|
|||
;; 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 <niwi@niwi.nz>
|
||||
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
;; Copyright (c) 2015-2017 Andrey Antukh <niwi@niwi.nz>
|
||||
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.workspace.sidebar.options.rect-measures
|
||||
(:require [lentes.core :as l]
|
||||
|
@ -23,28 +23,22 @@
|
|||
(mx/defc rect-measures-menu
|
||||
{:mixins [mx/static]}
|
||||
[menu {:keys [id] :as shape}]
|
||||
(letfn [(on-size-change [attr event]
|
||||
(let [value (-> (dom/event->value event) (parse-int 0))
|
||||
sid (:id shape)
|
||||
props {attr value}]
|
||||
(st/emit! (uds/update-size sid props))))
|
||||
(letfn [(on-size-change [event attr]
|
||||
(let [value (-> (dom/event->value event)
|
||||
(parse-int 0))]
|
||||
(st/emit! (uds/update-size id {attr value}))))
|
||||
(on-rotation-change [event]
|
||||
(let [value (dom/event->value event)
|
||||
value (parse-int value 0)
|
||||
sid (:id shape)]
|
||||
(st/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}]
|
||||
(st/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}]
|
||||
(st/emit! (uds/update-radius-attrs sid props))))
|
||||
(let [value (-> (dom/event->value event)
|
||||
(parse-int 0))]
|
||||
(st/emit! (uds/update-rotation id value))))
|
||||
(on-pos-change [event attr]
|
||||
(let [value (-> (dom/event->value event)
|
||||
(parse-int nil))]
|
||||
(st/emit! (uds/update-position id {attr value}))))
|
||||
(on-border-change [event attr]
|
||||
(let [value (-> (dom/event->value event)
|
||||
(parse-int nil))]
|
||||
(st/emit! (uds/update-attrs id {attr value}))))
|
||||
(on-proportion-lock-change [event]
|
||||
(if (:proportion-lock shape)
|
||||
(st/emit! (uds/unlock-proportions id))
|
||||
|
@ -62,7 +56,7 @@
|
|||
:type "number"
|
||||
:min "0"
|
||||
:value (precision-or-0 (:width size) 2)
|
||||
:on-change (partial on-size-change :width)}]]
|
||||
:on-change #(on-size-change % :width)}]]
|
||||
[:div.lock-size
|
||||
{:class (when (:proportion-lock shape) "selected")
|
||||
:on-click on-proportion-lock-change}
|
||||
|
@ -73,7 +67,7 @@
|
|||
:type "number"
|
||||
:min "0"
|
||||
:value (precision-or-0 (:height size) 2)
|
||||
:on-change (partial on-size-change :height)}]]]
|
||||
:on-change #(on-size-change % :height)}]]]
|
||||
|
||||
[:span "Position"]
|
||||
[:div.row-flex
|
||||
|
@ -82,13 +76,13 @@
|
|||
{:placeholder "x"
|
||||
:type "number"
|
||||
:value (precision-or-0 (:x1 shape 0) 2)
|
||||
:on-change (partial on-pos-change :x)}]]
|
||||
:on-change #(on-pos-change % :x)}]]
|
||||
[:div.input-element.pixels
|
||||
[:input.input-text
|
||||
{:placeholder "y"
|
||||
:type "number"
|
||||
:value (precision-or-0 (:y1 shape 0) 2)
|
||||
:on-change (partial on-pos-change :y)}]]]
|
||||
:on-change #(on-pos-change % :y)}]]]
|
||||
|
||||
[:span "Border radius"]
|
||||
[:div.row-flex
|
||||
|
@ -96,13 +90,13 @@
|
|||
{:placeholder "rx"
|
||||
:type "number"
|
||||
:value (precision-or-0 (:rx shape 0) 2)
|
||||
:on-change (partial on-border-change :rx)}]
|
||||
:on-change #(on-border-change % :rx)}]
|
||||
[:div.lock-size i/lock]
|
||||
[:input.input-text
|
||||
{:placeholder "ry"
|
||||
:type "number"
|
||||
:value (precision-or-0 (:ry shape 0) 2)
|
||||
:on-change (partial on-border-change :ry)}]]
|
||||
:on-change #(on-border-change % :ry)}]]
|
||||
|
||||
[:span "Rotation"]
|
||||
[:div.row-flex
|
||||
|
|
|
@ -2,13 +2,11 @@
|
|||
;; 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 <niwi@niwi.nz>
|
||||
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
;; Copyright (c) 2015-2017 Andrey Antukh <niwi@niwi.nz>
|
||||
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.workspace.sidebar.options.stroke
|
||||
(:require [sablono.core :as html :refer-macros [html]]
|
||||
[rum.core :as rum]
|
||||
[lentes.core :as l]
|
||||
(:require [lentes.core :as l]
|
||||
[uxbox.util.i18n :refer (tr)]
|
||||
[uxbox.util.router :as r]
|
||||
[potok.core :as ptk]
|
||||
|
@ -22,81 +20,73 @@
|
|||
[uxbox.util.math :refer (precision-or-0)]
|
||||
[uxbox.util.spec :refer (color?)]))
|
||||
|
||||
(defn- stroke-menu-render
|
||||
[own menu shape]
|
||||
(letfn [(change-stroke [value]
|
||||
(let [sid (:id shape)]
|
||||
(st/emit! (uds/update-stroke-attrs sid value))))
|
||||
(mx/defc stroke-menu
|
||||
{:mixed [mx/static]}
|
||||
[menu {:keys [id] :as shape}]
|
||||
(letfn [(update-attrs [attrs]
|
||||
(st/emit! (uds/update-attrs id attrs)))
|
||||
(on-width-change [event]
|
||||
(let [value (dom/event->value event)
|
||||
value (parse-float value 1)]
|
||||
(change-stroke {:width value})))
|
||||
(let [value (-> (dom/event->value event)
|
||||
(parse-float 1))]
|
||||
(update-attrs {: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})))
|
||||
(let [value (-> (dom/event->value event)
|
||||
(parse-float 1)
|
||||
(/ 10000))]
|
||||
(update-attrs {:stroke-opacity value})))
|
||||
(on-stroke-style-change [event]
|
||||
(let [value (dom/event->value event)
|
||||
value (read-string value)]
|
||||
(change-stroke {:type value})))
|
||||
(let [value (-> (dom/event->value event)
|
||||
(read-string))]
|
||||
(update-attrs {:stroke-style value})))
|
||||
(on-stroke-color-change [event]
|
||||
(let [value (dom/event->value event)]
|
||||
(when (color? value)
|
||||
(change-stroke {:color value}))))
|
||||
(update-attrs {:stroke-color value}))))
|
||||
(show-color-picker [event]
|
||||
(let [x (.-clientX event)
|
||||
y (.-clientY event)
|
||||
opts {:x x :y y
|
||||
:shape (:id shape)
|
||||
:attr :stroke
|
||||
:attr :stroke-color
|
||||
:transparent? true}]
|
||||
(udl/open! :workspace/shape-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"]]
|
||||
[:div.input-element.pixels
|
||||
[:input.input-text
|
||||
{:placeholder "Width"
|
||||
:type "number"
|
||||
:min "0"
|
||||
:value (precision-or-0 (:stroke-width shape 1) 2)
|
||||
:on-change on-width-change}]]]
|
||||
[: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 (pr-str (:stroke-style 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"]]
|
||||
[:div.input-element.pixels
|
||||
[:input.input-text
|
||||
{:placeholder "Width"
|
||||
:type "number"
|
||||
:min "0"
|
||||
:value (precision-or-0 (:stroke-width shape 1) 2)
|
||||
:on-change on-width-change}]]]
|
||||
|
||||
[:span "Color"]
|
||||
[:div.row-flex.color-data
|
||||
[:span.color-th
|
||||
{:style {:background-color (:stroke shape "#000000")}
|
||||
:on-click show-color-picker}]
|
||||
[:div.color-info
|
||||
[:input
|
||||
{:on-change on-stroke-color-change
|
||||
:value (:stroke shape "#000000")}]]]
|
||||
[:span "Color"]
|
||||
[:div.row-flex.color-data
|
||||
[:span.color-th
|
||||
{:style {:background-color (:stroke-color shape)}
|
||||
:on-click show-color-picker}]
|
||||
[:div.color-info
|
||||
[:input
|
||||
{:on-change on-stroke-color-change
|
||||
:value (:stroke-color 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]}))
|
||||
[:span "Opacity"]
|
||||
[:div.row-flex
|
||||
[:input.slidebar
|
||||
{:type "range"
|
||||
:min "0"
|
||||
:max "10000"
|
||||
:value (* 10000 (:stroke-opacity shape))
|
||||
:step "1"
|
||||
:on-change on-opacity-change}]]]]))
|
||||
|
|
|
@ -2,13 +2,11 @@
|
|||
;; 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 <niwi@niwi.nz>
|
||||
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
;; Copyright (c) 2015-2017 Andrey Antukh <niwi@niwi.nz>
|
||||
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.workspace.sidebar.options.text
|
||||
(:require [sablono.core :as html :refer-macros [html]]
|
||||
[rum.core :as rum]
|
||||
[lentes.core :as l]
|
||||
(:require [lentes.core :as l]
|
||||
[uxbox.util.i18n :refer (tr)]
|
||||
[uxbox.util.router :as r]
|
||||
[potok.core :as ptk]
|
||||
|
@ -30,136 +28,128 @@
|
|||
(declare +fonts+)
|
||||
(declare +fonts-by-id+)
|
||||
|
||||
(defn- text-menu-render
|
||||
[own menu {:keys [font] :as shape}]
|
||||
(letfn [(on-font-family-change [event]
|
||||
(mx/defc text-menu
|
||||
{:mixins [mx/static]}
|
||||
[menu {:keys [id] :as shape}]
|
||||
(letfn [(update-attrs [attrs]
|
||||
(st/emit! (uds/update-attrs id attrs)))
|
||||
(on-font-family-change [event]
|
||||
(let [value (dom/event->value event)
|
||||
sid (:id shape)
|
||||
params {:family (read-string value)
|
||||
:weight "normal"
|
||||
:style "normal"}]
|
||||
(st/emit! (uds/update-font-attrs sid params))))
|
||||
attrs {:font-family (read-string value)
|
||||
:font-weight "normal"
|
||||
:font-style "normal"}]
|
||||
(update-attrs attrs)))
|
||||
(on-font-size-change [event]
|
||||
(let [value (dom/event->value event)
|
||||
params {:size (parse-int value)}
|
||||
sid (:id shape)]
|
||||
(st/emit! (uds/update-font-attrs sid params))))
|
||||
(let [value (-> (dom/event->value event)
|
||||
(parse-int 0))]
|
||||
(update-attrs {:font-size value})))
|
||||
(on-font-letter-spacing-change [event]
|
||||
(let [value (dom/event->value event)
|
||||
params {:letter-spacing (parse-float value)}
|
||||
sid (:id shape)]
|
||||
(st/emit! (uds/update-font-attrs sid params))))
|
||||
(let [value (-> (dom/event->value event)
|
||||
(parse-float))]
|
||||
(update-attrs {:letter-spacing value})))
|
||||
(on-font-line-height-change [event]
|
||||
(let [value (dom/event->value event)
|
||||
params {:line-height (parse-float value)}
|
||||
sid (:id shape)]
|
||||
(st/emit! (uds/update-font-attrs sid params))))
|
||||
(let [value (-> (dom/event->value event)
|
||||
(parse-float))]
|
||||
(update-attrs {:line-height value})))
|
||||
(on-font-align-change [event value]
|
||||
(let [params {:align value}
|
||||
sid (:id shape)]
|
||||
(st/emit! (uds/update-font-attrs sid params))))
|
||||
|
||||
(update-attrs {:text-align value}))
|
||||
(on-font-style-change [event]
|
||||
(let [value (dom/event->value event)
|
||||
[weight style] (read-string value)
|
||||
sid (:id shape)
|
||||
params {:style style
|
||||
:weight weight}]
|
||||
(st/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"
|
||||
(let [[weight style] (-> (dom/event->value event)
|
||||
(read-string))]
|
||||
(update-attrs {:font-style style
|
||||
:font-weight weight})))]
|
||||
(let [{:keys [font-family
|
||||
font-style
|
||||
font-weight
|
||||
font-size
|
||||
text-align
|
||||
line-height
|
||||
letter-spacing]
|
||||
:or {font-family "sourcesanspro"
|
||||
font-style "normal"
|
||||
font-weight "normal"
|
||||
font-size 16
|
||||
text-align "left"
|
||||
letter-spacing 1
|
||||
line-height 1.4
|
||||
size 16}} font
|
||||
styles (:styles (first (filter #(= (:id %) family) +fonts+)))]
|
||||
(html
|
||||
[:div.element-set {:key (str (:id menu))}
|
||||
[:div.element-set-title (:name menu)]
|
||||
[:div.element-set-content
|
||||
line-height 1.4}} shape
|
||||
styles (:styles (first (filter #(= (:id %) font-family) +fonts+)))]
|
||||
[: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 +fonts+]
|
||||
[:option {:value (pr-str (:id font))
|
||||
:key (:id font)} (:name font)])]]
|
||||
[:span "Font family"]
|
||||
[:div.row-flex
|
||||
[:select.input-select {:value (pr-str font-family)
|
||||
:on-change on-font-family-change}
|
||||
(for [font +fonts+]
|
||||
[:option {:value (pr-str (:id font))
|
||||
:key (:id font)} (:name font)])]]
|
||||
|
||||
[:span "Size and Weight"]
|
||||
[:div.row-flex
|
||||
[:div.editable-select
|
||||
[:select.input-select
|
||||
{:id "common-font-sizes"
|
||||
:on-change on-font-size-change}
|
||||
[:option {:value "8"} "8"]
|
||||
[:option {:value "9"} "9"]
|
||||
[:option {:value "10"} "10"]
|
||||
[:option {:value "11"} "11"]
|
||||
[:option {:value "12"} "12"]
|
||||
[:option {:value "14"} "14"]
|
||||
[:option {:value "18"} "18"]
|
||||
[:option {:value "24"} "24"]
|
||||
[:option {:value "36"} "36"]
|
||||
[:option {:value "48"} "48"]
|
||||
[:option {:value "72"} "72"]]
|
||||
[:input.input-text
|
||||
{:placeholder "Font Size"
|
||||
:type "number"
|
||||
:min "0"
|
||||
:max "200"
|
||||
:value (precision-or-0 size 2)
|
||||
: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
|
||||
[:span "Size and Weight"]
|
||||
[:div.row-flex
|
||||
[:div.editable-select
|
||||
[:select.input-select
|
||||
{:id "common-font-sizes"
|
||||
:value font-size
|
||||
:on-change on-font-size-change}
|
||||
[:option {:value "8"} "8"]
|
||||
[:option {:value "9"} "9"]
|
||||
[:option {:value "10"} "10"]
|
||||
[:option {:value "11"} "11"]
|
||||
[:option {:value "12"} "12"]
|
||||
[:option {:value "14"} "14"]
|
||||
[:option {:value "18"} "18"]
|
||||
[:option {:value "24"} "24"]
|
||||
[:option {:value "36"} "36"]
|
||||
[:option {:value "48"} "48"]
|
||||
[:option {:value "72"} "72"]]
|
||||
[:input.input-text
|
||||
{:placeholder "Line height"
|
||||
{:placeholder "Font Size"
|
||||
:type "number"
|
||||
:step "0.1"
|
||||
:min "0"
|
||||
:max "200"
|
||||
:value (precision-or-0 line-height 2)
|
||||
:on-change on-font-line-height-change}]
|
||||
[:input.input-text
|
||||
{:placeholder "Letter spacing"
|
||||
:type "number"
|
||||
:step "0.1"
|
||||
:min "0"
|
||||
:max "200"
|
||||
:value (precision-or-0 letter-spacing 2)
|
||||
:on-change on-font-letter-spacing-change}]]
|
||||
:value (precision-or-0 font-size 2)
|
||||
:on-change on-font-size-change}]]
|
||||
[:select.input-select {:value (pr-str [font-weight font-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 (precision-or-0 line-height 2)
|
||||
:on-change on-font-line-height-change}]
|
||||
[:input.input-text
|
||||
{:placeholder "Letter spacing"
|
||||
:type "number"
|
||||
:step "0.1"
|
||||
:min "0"
|
||||
:max "200"
|
||||
:value (precision-or-0 letter-spacing 2)
|
||||
: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]}))
|
||||
|
||||
[:span "Text align"]
|
||||
[:div.row-flex.align-icons
|
||||
[:span {:class (when (= text-align "left") "current")
|
||||
:on-click #(on-font-align-change % "left")}
|
||||
i/align-left]
|
||||
[:span {:class (when (= text-align "right") "current")
|
||||
:on-click #(on-font-align-change % "right")}
|
||||
i/align-right]
|
||||
[:span {:class (when (= text-align "center") "current")
|
||||
:on-click #(on-font-align-change % "center")}
|
||||
i/align-center]
|
||||
[:span {:class (when (= text-align "justify") "current")
|
||||
:on-click #(on-font-align-change % "justify")}
|
||||
i/align-justify]]]])))
|
||||
|
||||
(def +fonts+
|
||||
[{:id "sourcesanspro"
|
||||
|
|
|
@ -45,3 +45,20 @@
|
|||
(when-not valid
|
||||
(js/console.error (str "Spec validation error:\n" (s/explain-str spec data))))
|
||||
valid))
|
||||
|
||||
(defn extract
|
||||
"Given a map spec, performs a `select-keys`
|
||||
like exctraction from the object.
|
||||
|
||||
NOTE: this function does not executes
|
||||
the conform or validation of the data,
|
||||
is responsability of the user to do it."
|
||||
[data spec]
|
||||
(let [desc (s/describe spec)
|
||||
{:keys [req-un opt-un]} (apply hash-map (rest desc))
|
||||
keys (concat
|
||||
(map (comp keyword name) req-un)
|
||||
(map (comp keyword name) opt-un))]
|
||||
(select-keys data keys)))
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue