0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-04-11 06:21:30 -05:00

🎉 Enhance line caps selectors

This commit is contained in:
Andrés Moya 2021-08-19 15:04:43 +02:00 committed by Andrey Antukh
parent 837985ccc5
commit eb40297a35
10 changed files with 149 additions and 38 deletions

View file

@ -0,0 +1 @@
<svg width="16" height="6" xmlns="http://www.w3.org/2000/svg"><rect rx="6" ry="6" x="10" width="6" height="6"/><path d="M0 3h14.5" fill="none" stroke="#000"/></svg>

After

Width:  |  Height:  |  Size: 165 B

View file

@ -0,0 +1 @@
<svg width="16" height="6" xmlns="http://www.w3.org/2000/svg"><rect rx="0" ry="0" x="11" y="1" transform="rotate(45 13 3)" width="4" height="4"/><path d="M0 3h14.5" fill="none" stroke="#000"/></svg>

After

Width:  |  Height:  |  Size: 199 B

View file

@ -0,0 +1 @@
<svg width="16" height="6" xmlns="http://www.w3.org/2000/svg"><path d="M0 3h14.5M11.7 0l1 1 1.6 2-2.6 3" fill="none" stroke="#000"/></svg>

After

Width:  |  Height:  |  Size: 139 B

View file

@ -0,0 +1 @@
<svg viewBox="1863 1374 16 8" width="16" height="8" xmlns="http://www.w3.org/2000/svg"><path d="M1879 1374h-12s-4 0-4 4 4 4 4 4h12" fill="none" stroke="#000"/></svg>

After

Width:  |  Height:  |  Size: 166 B

View file

@ -0,0 +1 @@
<svg width="16" height="6" xmlns="http://www.w3.org/2000/svg"><rect rx="0" ry="0" x="10" width="6" height="6" fill="#070707"/><path d="M0 3h14.5" fill="none" stroke="#000"/></svg>

After

Width:  |  Height:  |  Size: 180 B

View file

@ -0,0 +1 @@
<svg viewBox="1863 1407 16 8" width="16" height="8" xmlns="http://www.w3.org/2000/svg"><path d="M1879 1407h-16v8h16" fill="none" stroke="#000"/></svg>

After

Width:  |  Height:  |  Size: 151 B

View file

@ -0,0 +1 @@
<svg width="16" height="6" xmlns="http://www.w3.org/2000/svg"><path d="M0 3h14.5" fill="none" stroke="#000"/><path d="M13 0l2.9 3L13 6V0z"/></svg>

After

Width:  |  Height:  |  Size: 147 B

View file

@ -1436,5 +1436,57 @@
}
}
}
}
.cap-select {
background-color: transparent;
border: 1px solid transparent;
border-bottom-color: $color-gray-40;
color: $color-gray-10;
cursor: pointer;
font-size: $fs11;
margin: $x-small;
overflow: hidden;
padding: $x-small;
padding-right: 20px;
position: relative;
text-overflow: ellipsis;
white-space: nowrap;
width: 100%;
& .cap-select-button {
svg {
fill: $color-gray-10;
height: 11px;
position: absolute;
right: 5px;
top: 6px;
width: 11px;
}
}
&:hover {
border-color: $color-gray-40;
}
&:focus {
border-color: $color-primary;
}
}
.cap-select-dropdown {
right: 5px;
top: 30px;
z-index: 12;
min-width: 200px;
position: fixed;
& li.separator {
border-top: 1px solid $color-gray-10;
}
& li img {
width: 16px;
margin-right: $small;
}
}

View file

@ -13,6 +13,7 @@
[app.main.data.workspace.colors :as dc]
[app.main.data.workspace.undo :as dwu]
[app.main.store :as st]
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
[app.util.dom :as dom]
@ -44,6 +45,26 @@
""
(pr-str value)))
(defn- stroke-cap-names []
[[nil (tr "workspace.options.stroke-cap.none") false]
[:line-arrow (tr "workspace.options.stroke-cap.line-arrow") true]
[:triangle-arrow (tr "workspace.options.stroke-cap.triangle-arrow") false]
[:square-marker (tr "workspace.options.stroke-cap.square-marker") false]
[:circle-marker (tr "workspace.options.stroke-cap.circle-marker") false]
[:diamond-marker (tr "workspace.options.stroke-cap.diamond-marker") false]
[:round (tr "workspace.options.stroke-cap.round") true]
[:square (tr "workspace.options.stroke-cap.square") false]])
(defn- value->name [value]
(if (= value :multiple)
"--"
(-> (d/seek #(= (first %) value) (stroke-cap-names))
(second))))
(defn- value->img [value]
(when (and value (not= value :multiple))
(str "images/cap-" (name value) ".svg")))
(mf/defc stroke-menu
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type" "show-caps"]))]}
[{:keys [ids type values show-caps] :as props}]
@ -53,8 +74,14 @@
(tr "workspace.options.stroke"))
show-options (not= (:stroke-style values :none) :none)
show-caps (and show-caps (= (:stroke-alignment values) :center))
show-caps (and show-caps (= (:stroke-alignment values) :center))
start-caps-state (mf/use-state {:open? false
:top 0
:left 0})
end-caps-state (mf/use-state {:open? false
:top 0
:left 0})
current-stroke-color {:color (:stroke-color values)
:opacity (:stroke-opacity values)
@ -105,21 +132,34 @@
(apply (partial assoc %) kvs)
%))
open-caps-select
(fn [caps-state]
(fn [event]
(let [window-size (dom/get-window-size)
target (dom/get-current-target event)
rect (dom/get-bounding-rect target)
top (+ (:bottom rect) 5)
left (if (< (+ (:left rect) 200) (:width window-size))
(:left rect)
(- (:width window-size) 205))]
(swap! caps-state assoc :open? true
:left left
:top top))))
close-caps-select
(fn [caps-state]
(fn [_]
(swap! caps-state assoc :open? false)))
on-stroke-cap-start-change
(fn [event]
(let [value (-> (dom/get-target event)
(dom/get-value)
(d/read-string))]
(when-not (str/empty? value)
(st/emit! (dch/update-shapes ids (update-cap-attr :stroke-cap-start value))))))
(fn [value]
(st/emit! (dch/update-shapes ids (update-cap-attr :stroke-cap-start value))))
on-stroke-cap-end-change
(fn [event]
(let [value (-> (dom/get-target event)
(dom/get-value)
(d/read-string))]
(when-not (str/empty? value)
(st/emit! (dch/update-shapes ids (update-cap-attr :stroke-cap-end value))))))
(fn [value]
(st/emit! (dch/update-shapes ids (update-cap-attr :stroke-cap-end value))))
on-stroke-cap-switch
(fn [_]
@ -199,34 +239,40 @@
;; Stroke Caps
(when show-caps
[:div.row-flex
[:select#style.input-select {:value (enum->string (:stroke-cap-start values))
:on-change on-stroke-cap-start-change}
(when (= (:stroke-cap-start values) :multiple)
[:option {:value ""} "--"])
[:option {:value ""} (tr "workspace.options.stroke-cap.none")]
[:option {:value ":line-arrow"} (tr "workspace.options.stroke-cap.line-arrow")]
[:option {:value ":triangle-arrow"} (tr "workspace.options.stroke-cap.triangle-arrow")]
[:option {:value ":square-marker"} (tr "workspace.options.stroke-cap.square-marker")]
[:option {:value ":circle-marker"} (tr "workspace.options.stroke-cap.circle-marker")]
[:option {:value ":diamond-marker"} (tr "workspace.options.stroke-cap.diamond-marker")]
[:option {:value ":round"} (tr "workspace.options.stroke-cap.round")]
[:option {:value ":square"} (tr "workspace.options.stroke-cap.square")]]
[:div.cap-select {:tab-index 0 ;; tab-index to make the element focusable
:on-click (open-caps-select start-caps-state)}
(value->name (:stroke-cap-start values))
[:span.cap-select-button
i/arrow-down]]
[:& dropdown {:show (:open? @start-caps-state)
:on-close (close-caps-select start-caps-state)}
[:ul.dropdown.cap-select-dropdown {:style {:top (:top @start-caps-state)
:left (:left @start-caps-state)}}
(for [[value label separator] (stroke-cap-names)]
(let [img (value->img value)]
[:li {:class (dom/classnames :separator separator)
:on-click #(on-stroke-cap-start-change value)}
(when img [:img {:src (value->img value)}])
label]))]]
[:div.element-set-actions-button {:on-click on-stroke-cap-switch}
i/switch]
[:select#style.input-select {:value (enum->string (:stroke-cap-end values))
:on-change on-stroke-cap-end-change}
(when (= (:stroke-cap-end values) :multiple)
[:option {:value ""} "--"])
[:option {:value ""} (tr "workspace.options.stroke-cap.none")]
[:option {:value ":line-arrow"} (tr "workspace.options.stroke-cap.line-arrow")]
[:option {:value ":triangle-arrow"} (tr "workspace.options.stroke-cap.triangle-arrow")]
[:option {:value ":square-marker"} (tr "workspace.options.stroke-cap.square-marker")]
[:option {:value ":circle-marker"} (tr "workspace.options.stroke-cap.circle-marker")]
[:option {:value ":diamond-marker"} (tr "workspace.options.stroke-cap.diamond-marker")]
[:option {:value ":round"} (tr "workspace.options.stroke-cap.round")]
[:option {:value ":square"} (tr "workspace.options.stroke-cap.square")]]])]]
[:div.cap-select {:tab-index 0
:on-click (open-caps-select end-caps-state)}
(value->name (:stroke-cap-end values))
[:span.cap-select-button
i/arrow-down]]
[:& dropdown {:show (:open? @end-caps-state)
:on-close (close-caps-select end-caps-state)}
[:ul.dropdown.cap-select-dropdown {:style {:top (:top @end-caps-state)
:left (:left @end-caps-state)}}
(for [[value label separator] (stroke-cap-names)]
(let [img (value->img value)]
[:li {:class (dom/classnames :separator separator)
:on-click #(on-stroke-cap-end-change value)}
(when img [:img {:src (value->img value)}])
label]))]]])]]
;; NO STROKE
[:div.element-set

View file

@ -86,6 +86,12 @@
[event]
(.-target event))
(defn get-current-target
"Extract the current target from event instance (different from target
when event triggered in a child of the suscribing element)."
[event]
(.-currentTarget event))
(defn get-parent
[dom]
(.-parentElement ^js dom))