mirror of
https://github.com/penpot/penpot.git
synced 2025-05-18 11:06:14 +02:00
commit
ea51a8d9b6
14 changed files with 120 additions and 82 deletions
|
@ -125,6 +125,10 @@
|
||||||
- [VIEWER] Cannot scroll down in code </> mode [Taiga #4655](https://tree.taiga.io/project/penpot/issue/4655)
|
- [VIEWER] Cannot scroll down in code </> mode [Taiga #4655](https://tree.taiga.io/project/penpot/issue/4655)
|
||||||
- Strange cursor behavior after clicking viewport with text tool [Taiga #4363](https://tree.taiga.io/project/penpot/issue/4363)
|
- Strange cursor behavior after clicking viewport with text tool [Taiga #4363](https://tree.taiga.io/project/penpot/issue/4363)
|
||||||
- Selected color affects all of them [Taiga #5285](https://tree.taiga.io/project/penpot/issue/5285)
|
- Selected color affects all of them [Taiga #5285](https://tree.taiga.io/project/penpot/issue/5285)
|
||||||
|
- Fix problem with shadow negative spread [Github #3421](https://github.com/penpot/penpot/issues/3421)
|
||||||
|
- Fix problem with linked colors to strokes [Github #3522](https://github.com/penpot/penpot/issues/3522)
|
||||||
|
- Fix problem with hand tool stuck [Github #3318](https://github.com/penpot/penpot/issues/3318)
|
||||||
|
- Fix problem with fix scrolling on nested elements [Github #3508](https://github.com/penpot/penpot/issues/3508)
|
||||||
|
|
||||||
|
|
||||||
## 1.19.5
|
## 1.19.5
|
||||||
|
|
|
@ -277,7 +277,7 @@
|
||||||
(update :fill-color-ref-file lookup-index)
|
(update :fill-color-ref-file lookup-index)
|
||||||
|
|
||||||
;; This covers the old shapes and the new :strokes
|
;; This covers the old shapes and the new :strokes
|
||||||
(uuid? (:storage-color-ref-file form))
|
(uuid? (:stroke-color-ref-file form))
|
||||||
(update :stroke-color-ref-file lookup-index)
|
(update :stroke-color-ref-file lookup-index)
|
||||||
|
|
||||||
;; This covers all text shapes that have typography referenced
|
;; This covers all text shapes that have typography referenced
|
||||||
|
|
|
@ -762,6 +762,13 @@
|
||||||
|
|
||||||
(recur frame-id frame-parents (rest selected))))))
|
(recur frame-id frame-parents (rest selected))))))
|
||||||
|
|
||||||
|
(defn fixed-scroll?
|
||||||
|
[shape]
|
||||||
|
^boolean
|
||||||
|
(and (:fixed-scroll shape)
|
||||||
|
(= (:parent-id shape) (:frame-id shape))
|
||||||
|
(not= (:frame-id shape) uuid/zero)))
|
||||||
|
|
||||||
(defn fixed?
|
(defn fixed?
|
||||||
[objects shape-id]
|
[objects shape-id]
|
||||||
(let [ids-to-check
|
(let [ids-to-check
|
||||||
|
@ -772,4 +779,4 @@
|
||||||
(take-while #(and (not= % uuid/zero) (not (root-frame? objects %))))))]
|
(take-while #(and (not= % uuid/zero) (not (root-frame? objects %))))))]
|
||||||
(boolean
|
(boolean
|
||||||
(->> ids-to-check
|
(->> ids-to-check
|
||||||
(d/seek (fn [id] (dm/get-in objects [id :fixed-scroll])))))))
|
(d/seek (fn [id] () (fixed-scroll? (get objects id))))))))
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
[app.common.types.component :as ctk]
|
[app.common.types.component :as ctk]
|
||||||
[app.common.types.container :as ctn]
|
[app.common.types.container :as ctn]
|
||||||
[app.common.types.modifiers :as ctm]
|
[app.common.types.modifiers :as ctm]
|
||||||
|
[app.common.types.shape-tree :as ctst]
|
||||||
[app.common.types.shape.attrs :refer [editable-attrs]]
|
[app.common.types.shape.attrs :refer [editable-attrs]]
|
||||||
[app.common.types.shape.layout :as ctl]
|
[app.common.types.shape.layout :as ctl]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
|
@ -193,13 +194,16 @@
|
||||||
(update :shapes #(d/removev ids %))
|
(update :shapes #(d/removev ids %))
|
||||||
(ctl/assign-cells objects))
|
(ctl/assign-cells objects))
|
||||||
|
|
||||||
ids (->> ids (remove #(ctl/position-absolute? objects %)))
|
ids (->> ids
|
||||||
|
(remove #(ctl/position-absolute? objects %))
|
||||||
|
(ctst/sort-z-index objects)
|
||||||
|
reverse)
|
||||||
|
|
||||||
frame (-> frame
|
frame (-> frame
|
||||||
(update :shapes d/concat-vec ids)
|
(update :shapes d/concat-vec ids)
|
||||||
(cond-> (some? cell)
|
(cond-> (some? cell)
|
||||||
(ctl/push-into-cell ids row column))
|
(ctl/push-into-cell ids row column))
|
||||||
(ctl/assign-cells objects))]
|
(ctl/assign-cells objects))]
|
||||||
|
|
||||||
(-> modifiers
|
(-> modifiers
|
||||||
(ctm/change-property :layout-grid-rows (:layout-grid-rows frame))
|
(ctm/change-property :layout-grid-rows (:layout-grid-rows frame))
|
||||||
(ctm/change-property :layout-grid-columns (:layout-grid-columns frame))
|
(ctm/change-property :layout-grid-columns (:layout-grid-columns frame))
|
||||||
|
|
|
@ -601,12 +601,16 @@
|
||||||
attrs (-> typography
|
attrs (-> typography
|
||||||
(assoc :typography-ref-file file-id)
|
(assoc :typography-ref-file file-id)
|
||||||
(assoc :typography-ref-id (:id typography))
|
(assoc :typography-ref-id (:id typography))
|
||||||
(dissoc :id :name))]
|
(dissoc :id :name))
|
||||||
|
undo-id (js/Symbol)]
|
||||||
|
|
||||||
(->> (rx/from (seq selected))
|
(rx/concat
|
||||||
(rx/map (fn [id]
|
(rx/of (dwu/start-undo-transaction undo-id))
|
||||||
(let [editor (get editor-state id)]
|
(->> (rx/from (seq selected))
|
||||||
(update-text-attrs {:id id :editor editor :attrs attrs})))))))))
|
(rx/map (fn [id]
|
||||||
|
(let [editor (get editor-state id)]
|
||||||
|
(update-text-attrs {:id id :editor editor :attrs attrs})))))
|
||||||
|
(rx/of (dwu/commit-undo-transaction undo-id)))))))
|
||||||
|
|
||||||
(defn generate-typography-name
|
(defn generate-typography-name
|
||||||
[{:keys [font-id font-variant-id] :as typography}]
|
[{:keys [font-id font-variant-id] :as typography}]
|
||||||
|
|
|
@ -151,6 +151,11 @@
|
||||||
(rx/filter kbd/space?)
|
(rx/filter kbd/space?)
|
||||||
(rx/filter (complement kbd/editing-event?))
|
(rx/filter (complement kbd/editing-event?))
|
||||||
(rx/map kbd/key-down-event?)
|
(rx/map kbd/key-down-event?)
|
||||||
|
;; Fix a situation caused by using `ctrl+alt` kind of
|
||||||
|
;; shortcuts, that makes keyboard-alt stream
|
||||||
|
;; registering the key pressed but on blurring the
|
||||||
|
;; window (unfocus) the key down is never arrived.
|
||||||
|
(rx/merge window-blur)
|
||||||
(rx/pipe (rxo/distinct-contiguous)))]
|
(rx/pipe (rxo/distinct-contiguous)))]
|
||||||
(rx/sub! ob sub)
|
(rx/sub! ob sub)
|
||||||
sub))
|
sub))
|
||||||
|
|
|
@ -107,8 +107,7 @@
|
||||||
(not= "0.0" (:main cf/version)))
|
(not= "0.0" (:main cf/version)))
|
||||||
[:& release-notes-modal {:version (:main cf/version)}]))
|
[:& release-notes-modal {:version (:main cf/version)}]))
|
||||||
|
|
||||||
(when profile
|
[:& dashboard-page {:route route :profile profile}]]
|
||||||
[:& dashboard-page {:route route :profile profile}])]
|
|
||||||
|
|
||||||
:viewer
|
:viewer
|
||||||
(let [{:keys [query-params path-params]} route
|
(let [{:keys [query-params path-params]} route
|
||||||
|
|
|
@ -372,7 +372,10 @@
|
||||||
in-klass (str class " "
|
in-klass (str class " "
|
||||||
(stl/css-case
|
(stl/css-case
|
||||||
:inside-input true
|
:inside-input true
|
||||||
:no-padding (pos? (count @items))))
|
:no-padding (pos? (count @items))
|
||||||
|
:invalid (and (some? valid-item-fn)
|
||||||
|
touched?
|
||||||
|
(not (valid-item-fn @value)))))
|
||||||
|
|
||||||
on-focus
|
on-focus
|
||||||
(mf/use-fn #(reset! focus? true))
|
(mf/use-fn #(reset! focus? true))
|
||||||
|
@ -394,27 +397,38 @@
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps @value)
|
(mf/deps @value)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(cond
|
(let [val (cond-> @value trim str/trim)]
|
||||||
(or (kbd/enter? event)
|
(cond
|
||||||
(kbd/comma? event))
|
(or (kbd/enter? event) (kbd/comma? event) (kbd/space? event))
|
||||||
(do
|
(do
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(let [val (cond-> @value trim str/trim)]
|
|
||||||
|
;; Once enter/comma is pressed we mark it as touched
|
||||||
|
(swap! form assoc-in [:touched input-name] true)
|
||||||
|
|
||||||
|
;; Empty values means "submit" the form (whent some items have been added
|
||||||
(when (and (kbd/enter? event) (str/empty? @value) (not-empty @items))
|
(when (and (kbd/enter? event) (str/empty? @value) (not-empty @items))
|
||||||
(on-submit form))
|
(on-submit form))
|
||||||
(when (not (str/empty? @value))
|
|
||||||
(reset! value "")
|
|
||||||
(swap! items conj-dedup {:text val
|
|
||||||
:valid (valid-item-fn val)
|
|
||||||
:caution (caution-item-fn val)}))))
|
|
||||||
|
|
||||||
(and (kbd/backspace? event)
|
;; If we have a string in the input we add it only if valid
|
||||||
(str/empty? @value))
|
(when (and (valid-item-fn val) (not (str/empty? @value)))
|
||||||
(do
|
(reset! value "")
|
||||||
(dom/prevent-default event)
|
|
||||||
(dom/stop-propagation event)
|
;; Once added the form is back as "untouched"
|
||||||
(swap! items (fn [items] (if (c/empty? items) items (pop items))))))))
|
(swap! form assoc-in [:touched input-name] false)
|
||||||
|
|
||||||
|
;; This split will allow users to copy comma/space separated values of emails
|
||||||
|
(doseq [val (str/split val #",|\s+")]
|
||||||
|
(swap! items conj-dedup {:text (str/trim val)
|
||||||
|
:valid (valid-item-fn val)
|
||||||
|
:caution (caution-item-fn val)}))))
|
||||||
|
|
||||||
|
(and (kbd/backspace? event) (str/empty? @value))
|
||||||
|
(do
|
||||||
|
(dom/prevent-default event)
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(swap! items (fn [items] (if (c/empty? items) items (pop items)))))))))
|
||||||
|
|
||||||
on-blur
|
on-blur
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
|
|
@ -293,6 +293,13 @@
|
||||||
outline: none;
|
outline: none;
|
||||||
border: $s-1 solid var(--input-border-color-focus);
|
border: $s-1 solid var(--input-border-color-focus);
|
||||||
}
|
}
|
||||||
|
&.invalid {
|
||||||
|
border: $s-1 solid var(--input-border-color-error);
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
border: $s-1 solid var(--input-border-color-error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
label {
|
label {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
@ -787,24 +787,25 @@
|
||||||
|
|
||||||
on-error
|
on-error
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [form {:keys [type code hint] :as error}]
|
(fn [form error]
|
||||||
(if (and (= type :validation)
|
(let [{:keys [type code hint]} (ex-data error)]
|
||||||
(= code :webhook-validation))
|
(if (and (= type :validation)
|
||||||
(let [message (cond
|
(= code :webhook-validation))
|
||||||
(= hint "unknown")
|
(let [message (cond
|
||||||
(tr "errors.webhooks.unexpected")
|
(= hint "unknown")
|
||||||
(= hint "invalid-uri")
|
(tr "errors.webhooks.unexpected")
|
||||||
(tr "errors.webhooks.invalid-uri")
|
(= hint "invalid-uri")
|
||||||
(= hint "ssl-validation-error")
|
(tr "errors.webhooks.invalid-uri")
|
||||||
(tr "errors.webhooks.ssl-validation")
|
(= hint "ssl-validation-error")
|
||||||
(= hint "timeout")
|
(tr "errors.webhooks.ssl-validation")
|
||||||
(tr "errors.webhooks.timeout")
|
(= hint "timeout")
|
||||||
(= hint "connection-error")
|
(tr "errors.webhooks.timeout")
|
||||||
(tr "errors.webhooks.connection")
|
(= hint "connection-error")
|
||||||
(str/starts-with? hint "unexpected-status")
|
(tr "errors.webhooks.connection")
|
||||||
(tr "errors.webhooks.unexpected-status" (extract-status hint)))]
|
(str/starts-with? hint "unexpected-status")
|
||||||
(swap! form assoc-in [:errors :uri] {:message message}))
|
(tr "errors.webhooks.unexpected-status" (extract-status hint)))]
|
||||||
(rx/throw error))))
|
(swap! form assoc-in [:errors :uri] {:message message}))
|
||||||
|
(rx/throw error)))))
|
||||||
|
|
||||||
on-create-submit
|
on-create-submit
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
|
|
@ -45,6 +45,12 @@
|
||||||
:in "SourceAlpha"
|
:in "SourceAlpha"
|
||||||
:result filter-id}])
|
:result filter-id}])
|
||||||
|
|
||||||
|
(when (< spread 0)
|
||||||
|
[:feMorphology {:radius (- spread)
|
||||||
|
:operator "erode"
|
||||||
|
:in "SourceAlpha"
|
||||||
|
:result filter-id}])
|
||||||
|
|
||||||
[:feOffset {:dx offset-x :dy offset-y}]
|
[:feOffset {:dx offset-x :dy offset-y}]
|
||||||
[:feGaussianBlur {:stdDeviation (/ blur 2)}]
|
[:feGaussianBlur {:stdDeviation (/ blur 2)}]
|
||||||
[:& color-matrix {:color color}]
|
[:& color-matrix {:color color}]
|
||||||
|
|
|
@ -7,18 +7,14 @@
|
||||||
(ns app.main.ui.viewer.inspect.attributes.stroke
|
(ns app.main.ui.viewer.inspect.attributes.stroke
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
|
||||||
[app.common.data.macros :as dm]
|
|
||||||
[app.main.ui.components.copy-button :refer [copy-button]]
|
|
||||||
[app.main.ui.components.title-bar :refer [inspect-title-bar]]
|
[app.main.ui.components.title-bar :refer [inspect-title-bar]]
|
||||||
[app.main.ui.formats :as fmt]
|
|
||||||
[app.main.ui.viewer.inspect.attributes.common :refer [color-row]]
|
[app.main.ui.viewer.inspect.attributes.common :refer [color-row]]
|
||||||
[app.util.code-gen.style-css-formats :as cssf]
|
[app.util.code-gen.style-css :as css]
|
||||||
[app.util.code-gen.style-css-values :as cssv]
|
|
||||||
[app.util.color :as uc]
|
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
(def properties [:border])
|
||||||
|
|
||||||
(defn stroke->color [shape]
|
(defn stroke->color [shape]
|
||||||
{:color (:stroke-color shape)
|
{:color (:stroke-color shape)
|
||||||
:opacity (:stroke-opacity shape)
|
:opacity (:stroke-opacity shape)
|
||||||
|
@ -31,30 +27,21 @@
|
||||||
(seq (:strokes shape)))
|
(seq (:strokes shape)))
|
||||||
|
|
||||||
(mf/defc stroke-block
|
(mf/defc stroke-block
|
||||||
[{:keys [stroke]}]
|
{::mf/wrap-props false}
|
||||||
(let [color-format (mf/use-state :hex)
|
[{:keys [objects shape]}]
|
||||||
color (stroke->color stroke)]
|
(let [format* (mf/use-state :hex)
|
||||||
[:div {:class (stl/css :attributes-stroke-block)}
|
format (deref format*)
|
||||||
(let [{:keys [stroke-style stroke-alignment]} stroke
|
color (stroke->color shape)
|
||||||
stroke-style (if (= stroke-style :svg) :solid stroke-style)
|
on-change
|
||||||
stroke-alignment (or stroke-alignment :center)
|
(mf/use-fn
|
||||||
stroke-def (dm/str (fmt/format-pixels (:stroke-width stroke)) " "
|
(fn [format]
|
||||||
(tr (dm/str "inspect.attributes.stroke.style." (or (d/name stroke-style) "none"))) " "
|
(reset! format* format)))]
|
||||||
(tr (dm/str "inspect.attributes.stroke.alignment." (d/name stroke-alignment))))]
|
[:div {:class (stl/css :attributes-fill-block)}
|
||||||
|
[:& color-row
|
||||||
[:*
|
{:color color
|
||||||
[:& color-row {:color color
|
:format format
|
||||||
:format @color-format
|
:on-change-format on-change
|
||||||
:copy-data (uc/color->background color)
|
:copy-data (css/get-shape-properties-css objects {:strokes [shape]} properties)}]]))
|
||||||
:on-change-format #(reset! color-format %)}]
|
|
||||||
|
|
||||||
[:div {:class (stl/css :stroke-row)}
|
|
||||||
[:div {:class (stl/css :global/attr-label)}
|
|
||||||
"Border"]
|
|
||||||
[:div {:class (stl/css :global/attr-value)}
|
|
||||||
|
|
||||||
[:& copy-button {:data (cssf/format-value :border (cssv/get-stroke-data stroke))}
|
|
||||||
[:div {:class (stl/css :button-children)} stroke-def]]]]])]))
|
|
||||||
|
|
||||||
(mf/defc stroke-panel
|
(mf/defc stroke-panel
|
||||||
[{:keys [shapes]}]
|
[{:keys [shapes]}]
|
||||||
|
@ -69,4 +56,4 @@
|
||||||
(for [shape shapes]
|
(for [shape shapes]
|
||||||
(for [value (:strokes shape)]
|
(for [value (:strokes shape)]
|
||||||
[:& stroke-block {:key (str "stroke-color-" (:id shape) value)
|
[:& stroke-block {:key (str "stroke-color-" (:id shape) value)
|
||||||
:stroke value}]))]])))
|
:shape value}]))]])))
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
|
|
||||||
(defn get-fixed-ids
|
(defn get-fixed-ids
|
||||||
[objects]
|
[objects]
|
||||||
(let [fixed-ids (filter :fixed-scroll (vals objects))
|
(let [fixed-ids (filter cfh/fixed-scroll? (vals objects))
|
||||||
|
|
||||||
;; we have to consider the children if the fixed element is a group
|
;; we have to consider the children if the fixed element is a group
|
||||||
fixed-children-ids
|
fixed-children-ids
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
|
|
||||||
accept-edit (fn []
|
accept-edit (fn []
|
||||||
(let [name-input (mf/ref-val name-ref)
|
(let [name-input (mf/ref-val name-ref)
|
||||||
name (dom/get-value name-input)]
|
name (str/trim (dom/get-value name-input))]
|
||||||
(reset! editing? false)
|
(reset! editing? false)
|
||||||
(st/emit! (dwi/end-rename-flow)
|
(st/emit! (dwi/end-rename-flow)
|
||||||
(when-not (str/empty? name)
|
(when-not (str/empty? name)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue