mirror of
https://github.com/penpot/penpot.git
synced 2025-02-13 18:48:37 -05:00
commit
9c7f4dfd98
11 changed files with 141 additions and 45 deletions
|
@ -44,7 +44,13 @@
|
|||
- Right click over artboard name to open its menu [Taiga #1679](https://tree.taiga.io/project/penpot/issue/1679)
|
||||
- Make the default session cookue use SameSite=Lax instead of Strict (causes some issues in latest versions of Chrome).
|
||||
- Fix "open in new tab" on dashboard [Taiga #2235](https://tree.taiga.io/project/penpot/issue/2355)
|
||||
- Changing pages while comments activated will not close the panel [#1350](https://github.com/penpot/penpot/issues/1350)
|
||||
- Fix navigate comments in right sidebar [Taiga #2163](https://tree.taiga.io/project/penpot/issue/2163)
|
||||
- Fix keep name of component equal to the shape name [Taiga #2341](https://tree.taiga.io/project/penpot/issue/2341)
|
||||
- Fix lossing changes when changing selection and an input was already changed [Taiga #2329](https://tree.taiga.io/project/penpot/issue/2329), [Taiga #2330](https://tree.taiga.io/project/penpot/issue/2330)
|
||||
- Fix blur input field when click on viewport [Taiga #2164](https://tree.taiga.io/project/penpot/issue/2164)
|
||||
- Fix default page id in workspace [Taiga #2205](https://tree.taiga.io/project/penpot/issue/2205)
|
||||
- Fix problem when importing a file with grids [Taiga #2314](https://tree.taiga.io/project/penpot/issue/2314)
|
||||
|
||||
### :arrow_up: Deps updates
|
||||
|
||||
|
@ -150,6 +156,7 @@
|
|||
- Remove button after import process finish [Taiga #2215](https://tree.taiga.io/project/penpot/issue/2215)
|
||||
- Fix problem with styles in the viewer [Taiga #2467](https://tree.taiga.io/project/penpot/issue/2467)
|
||||
- Fix default state in viewer [Taiga #2465](https://tree.taiga.io/project/penpot/issue/2465)
|
||||
- Fix division by zero in bool operation [Taiga #2349](https://tree.taiga.io/project/penpot/issue/2349)
|
||||
|
||||
### :heart: Community contributions by (Thank you!)
|
||||
|
||||
|
|
|
@ -119,7 +119,9 @@
|
|||
;; normalize value
|
||||
d (mth/sqrt (+ (* x x) (* y y)))]
|
||||
|
||||
(gpt/point (/ x d) (/ y d))))
|
||||
(if (mth/almost-zero? d)
|
||||
(gpt/point 0 0)
|
||||
(gpt/point (/ x d) (/ y d)))))
|
||||
|
||||
(defn curve-windup
|
||||
[curve t]
|
||||
|
|
|
@ -29,12 +29,12 @@
|
|||
:artboard-grid/color]))
|
||||
|
||||
(s/def :artboard-grid/column
|
||||
(s/keys :req-un [:artboard-grid/size
|
||||
:artboard-grid/color
|
||||
(s/keys :req-un [:artboard-grid/color]
|
||||
:opt-un [:artboard-grid/size
|
||||
:artboard-grid/type
|
||||
:artboard-grid/item-length
|
||||
:artboard-grid/margin
|
||||
:artboard-grid/gutter]
|
||||
:opt-un [:artboard-grid/type
|
||||
:artboard-grid/item-length]))
|
||||
:artboard-grid/gutter]))
|
||||
|
||||
(s/def :artboard-grid/row :artboard-grid/column)
|
||||
|
||||
|
|
|
@ -253,17 +253,24 @@
|
|||
(->> (rx/of ::dwp/finalize)
|
||||
(rx/observe-on :async))))))
|
||||
|
||||
(declare go-to-page)
|
||||
(defn initialize-page
|
||||
[page-id]
|
||||
(us/assert ::us/uuid page-id)
|
||||
(ptk/reify ::initialize-page
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(when-not (contains? (get-in state [:workspace-data :pages-index]) page-id)
|
||||
(let [default-page-id (get-in state [:workspace-data :pages 0])]
|
||||
(rx/of (go-to-page default-page-id)))))
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [;; we maintain a cache of page state for user convenience
|
||||
;; with the exception of the selection; when user abandon
|
||||
;; the current page, the selection is lost
|
||||
|
||||
page (get-in state [:workspace-data :pages-index page-id])
|
||||
page-id (:id page)
|
||||
local (-> state
|
||||
(get-in [:workspace-cache page-id] workspace-local-default)
|
||||
(assoc :selected (d/ordered-set)))]
|
||||
|
@ -282,10 +289,13 @@
|
|||
(let [local (-> (:workspace-local state)
|
||||
(dissoc :edition
|
||||
:edit-path
|
||||
:selected))]
|
||||
(-> state
|
||||
(assoc-in [:workspace-cache page-id] local)
|
||||
(dissoc :current-page-id :workspace-local :trimmed-page :workspace-drawing))))))
|
||||
:selected))
|
||||
exit-workspace? (not= :workspace (get-in state [:route :data :name]))]
|
||||
(cond-> (assoc-in state [:workspace-cache page-id] local)
|
||||
:always
|
||||
(dissoc :current-page-id :workspace-local :trimmed-page)
|
||||
exit-workspace?
|
||||
(dissoc :workspace-drawing))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Workspace Page CRUD
|
||||
|
@ -416,9 +426,9 @@
|
|||
(-> local
|
||||
(assoc :vport size)
|
||||
(update :vbox (fn [vbox]
|
||||
(-> vbox
|
||||
(update :width #(/ % wprop))
|
||||
(update :height #(/ % hprop))))))))
|
||||
(-> vbox
|
||||
(update :width #(/ % wprop))
|
||||
(update :height #(/ % hprop))))))))
|
||||
|
||||
(initialize [state local]
|
||||
(let [page-id (:current-page-id state)
|
||||
|
@ -445,7 +455,7 @@
|
|||
:y (+ (:y srect) (/ (- (:height srect) height) 2)))))))
|
||||
|
||||
(setup [state local]
|
||||
(if (and (:vbox local) (:vport local))
|
||||
(if (and (:vport local) (:vbox local))
|
||||
(update* local)
|
||||
(initialize state local)))]
|
||||
|
||||
|
|
|
@ -76,15 +76,13 @@
|
|||
(update [_ state]
|
||||
(update state :workspace-local
|
||||
(fn [{:keys [vbox zoom] :as local}]
|
||||
(let [pw (/ 50 zoom)
|
||||
ph (/ 200 zoom)
|
||||
(let [pw (/ 160 zoom)
|
||||
ph (/ 160 zoom)
|
||||
nw (mth/round (- (/ (:width vbox) 2) pw))
|
||||
nh (mth/round (- (/ (:height vbox) 2) ph))
|
||||
nx (- (:x position) nw)
|
||||
ny (- (:y position) nh)]
|
||||
|
||||
|
||||
(update local :vbox assoc :x nx :y ny)))))))
|
||||
(update local :vbox assoc :x nx :y ny)))))))
|
||||
|
||||
(defn navigate
|
||||
[thread]
|
||||
|
|
|
@ -130,11 +130,12 @@
|
|||
(if (and (= (count shapes) 1)
|
||||
(:component-id (first shapes)))
|
||||
empty-changes
|
||||
(let [[group rchanges uchanges]
|
||||
(let [name (if (= 1 (count shapes)) (:name (first shapes)) "Component-1")
|
||||
[group rchanges uchanges]
|
||||
(if (and (= (count shapes) 1)
|
||||
(= (:type (first shapes)) :group))
|
||||
[(first shapes) [] []]
|
||||
(dwg/prepare-create-group objects page-id shapes "Component-1" true))
|
||||
(dwg/prepare-create-group objects page-id shapes name true))
|
||||
|
||||
;; Asserts for documentation purposes
|
||||
_ (us/assert vector? rchanges)
|
||||
|
@ -146,7 +147,7 @@
|
|||
rchanges (conj rchanges
|
||||
{:type :add-component
|
||||
:id (:id new-shape)
|
||||
:name (:name new-shape)
|
||||
:name name
|
||||
:shapes new-shapes})
|
||||
|
||||
rchanges (into rchanges
|
||||
|
|
|
@ -8,10 +8,20 @@
|
|||
(:require
|
||||
[app.util.color :as uc]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.globals :as globals]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.keyboard :as kbd]
|
||||
[app.util.object :as obj]
|
||||
[rumext.alpha :as mf]))
|
||||
[goog.events :as events]
|
||||
[rumext.alpha :as mf])
|
||||
(:import goog.events.EventType))
|
||||
|
||||
(defn clean-color
|
||||
[value]
|
||||
(-> value
|
||||
(uc/expand-hex)
|
||||
(uc/parse-color)
|
||||
(uc/prepend-hash)))
|
||||
|
||||
(mf/defc color-input
|
||||
{::mf/wrap-props false
|
||||
|
@ -26,16 +36,17 @@
|
|||
local-ref (mf/use-ref)
|
||||
ref (or external-ref local-ref)
|
||||
|
||||
;; We need to store the handle-blur ref so we can call it on unmount
|
||||
handle-blur-ref (mf/use-ref nil)
|
||||
dirty-ref (mf/use-ref false)
|
||||
|
||||
parse-value
|
||||
(mf/use-callback
|
||||
(mf/deps ref)
|
||||
(fn []
|
||||
(let [input-node (mf/ref-val ref)]
|
||||
(try
|
||||
(let [new-value (-> (dom/get-value input-node)
|
||||
(uc/expand-hex)
|
||||
(uc/parse-color)
|
||||
(uc/prepend-hash))]
|
||||
(let [new-value (clean-color (dom/get-value input-node))]
|
||||
(dom/set-validity! input-node "")
|
||||
new-value)
|
||||
(catch :default _e
|
||||
|
@ -53,7 +64,8 @@
|
|||
(mf/use-callback
|
||||
(mf/deps on-change update-input)
|
||||
(fn [new-value]
|
||||
(when new-value
|
||||
(mf/set-ref-val! dirty-ref false)
|
||||
(when (and new-value (not= (uc/remove-hash new-value) value))
|
||||
(when on-change
|
||||
(on-change new-value))
|
||||
(update-input new-value))))
|
||||
|
@ -62,6 +74,7 @@
|
|||
(mf/use-callback
|
||||
(mf/deps apply-value update-input)
|
||||
(fn [event]
|
||||
(mf/set-ref-val! dirty-ref true)
|
||||
(let [enter? (kbd/enter? event)
|
||||
esc? (kbd/esc? event)]
|
||||
(when enter?
|
||||
|
@ -81,7 +94,14 @@
|
|||
(apply-value new-value)
|
||||
(update-input value)))))
|
||||
|
||||
;; list-id (str "colors-" (uuid/next))
|
||||
on-click
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(let [target (dom/get-target event)]
|
||||
(when (some? ref)
|
||||
(let [current (mf/ref-val ref)]
|
||||
(when (and (some? current) (not (.contains current target)))
|
||||
(dom/blur! current)))))))
|
||||
|
||||
props (-> props
|
||||
(obj/without ["value" "onChange"])
|
||||
|
@ -98,6 +118,25 @@
|
|||
(when-let [node (mf/ref-val ref)]
|
||||
(dom/set-value! node value))))
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps handle-blur)
|
||||
(fn []
|
||||
(mf/set-ref-val! handle-blur-ref {:fn handle-blur})))
|
||||
|
||||
(mf/use-layout-effect
|
||||
(fn []
|
||||
#(when (mf/ref-val dirty-ref)
|
||||
(let [handle-blur (:fn (mf/ref-val handle-blur-ref))]
|
||||
(handle-blur)))))
|
||||
|
||||
(mf/use-layout-effect
|
||||
(fn []
|
||||
(let [keys [(events/listen globals/window EventType.POINTERDOWN on-click)
|
||||
(events/listen globals/window EventType.MOUSEDOWN on-click)
|
||||
(events/listen globals/window EventType.CLICK on-click)]]
|
||||
#(doseq [key keys]
|
||||
(events/unlistenByKey key)))))
|
||||
|
||||
[:*
|
||||
[:> :input props]
|
||||
;; FIXME: this causes some weird interactions because of using apply-value
|
||||
|
|
|
@ -10,11 +10,14 @@
|
|||
[app.common.math :as math]
|
||||
[app.common.spec :as us]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.globals :as globals]
|
||||
[app.util.keyboard :as kbd]
|
||||
[app.util.object :as obj]
|
||||
[app.util.simple-math :as sm]
|
||||
[app.util.strings :as ust]
|
||||
[rumext.alpha :as mf]))
|
||||
[goog.events :as events]
|
||||
[rumext.alpha :as mf])
|
||||
(:import goog.events.EventType))
|
||||
|
||||
(defn num? [val]
|
||||
(and (number? val)
|
||||
|
@ -42,6 +45,10 @@
|
|||
local-ref (mf/use-ref)
|
||||
ref (or external-ref local-ref)
|
||||
|
||||
;; We need to store the handle-blur ref so we can call it on unmount
|
||||
handle-blur-ref (mf/use-ref nil)
|
||||
dirty-ref (mf/use-ref false)
|
||||
|
||||
;; This `value` represents the previous value and is used as
|
||||
;; initil value for the simple math expression evaluation.
|
||||
value (d/parse-integer value-str default-val)
|
||||
|
@ -104,6 +111,7 @@
|
|||
(mf/use-callback
|
||||
(mf/deps on-change update-input value)
|
||||
(fn [new-value]
|
||||
(mf/set-ref-val! dirty-ref false)
|
||||
(when (and (not= new-value value) (some? on-change))
|
||||
(on-change new-value))
|
||||
(update-input new-value)))
|
||||
|
@ -142,6 +150,7 @@
|
|||
(mf/use-callback
|
||||
(mf/deps set-delta apply-value update-input)
|
||||
(fn [event]
|
||||
(mf/set-ref-val! dirty-ref true)
|
||||
(let [up? (kbd/up-arrow? event)
|
||||
down? (kbd/down-arrow? event)
|
||||
enter? (kbd/enter? event)
|
||||
|
@ -170,6 +179,15 @@
|
|||
(update-input new-value)))
|
||||
(when on-blur (on-blur))))
|
||||
|
||||
on-click
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(let [target (dom/get-target event)]
|
||||
(when (some? ref)
|
||||
(let [current (mf/ref-val ref)]
|
||||
(when (and (some? current) (not (.contains current target)))
|
||||
(dom/blur! current)))))))
|
||||
|
||||
props (-> props
|
||||
(obj/without ["value" "onChange"])
|
||||
(obj/set! "className" "input-text")
|
||||
|
@ -188,5 +206,24 @@
|
|||
(when-not (dom/active? input-node)
|
||||
(dom/set-value! input-node value-str)))))
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps handle-blur)
|
||||
(fn []
|
||||
(mf/set-ref-val! handle-blur-ref {:fn handle-blur})))
|
||||
|
||||
(mf/use-layout-effect
|
||||
(fn []
|
||||
#(when (mf/ref-val dirty-ref)
|
||||
(let [handle-blur (:fn (mf/ref-val handle-blur-ref))]
|
||||
(handle-blur)))))
|
||||
|
||||
(mf/use-layout-effect
|
||||
(fn []
|
||||
(let [keys [(events/listen globals/window EventType.POINTERDOWN on-click)
|
||||
(events/listen globals/window EventType.MOUSEDOWN on-click)
|
||||
(events/listen globals/window EventType.CLICK on-click)]]
|
||||
#(doseq [key keys]
|
||||
(events/unlistenByKey key)))))
|
||||
|
||||
[:> :input props]))
|
||||
|
||||
|
|
|
@ -87,7 +87,8 @@
|
|||
|
||||
(mf/defc workspace-page
|
||||
[{:keys [file layout page-id] :as props}]
|
||||
(mf/use-layout-effect
|
||||
|
||||
(mf/use-layout-effect
|
||||
(mf/deps page-id)
|
||||
(fn []
|
||||
(if (nil? page-id)
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
[app.main.data.workspace.colors :as dc]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
|
||||
[app.util.dom :as dom]
|
||||
|
@ -208,11 +209,12 @@
|
|||
[:div.input-element
|
||||
{:class (dom/classnames :pixels (not= (:stroke-width values) :multiple))
|
||||
:title (tr "workspace.options.stroke-width")}
|
||||
[:input.input-text {:type "number"
|
||||
:min "0"
|
||||
:value (-> (:stroke-width values) width->string)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:on-change on-stroke-width-change}]]
|
||||
|
||||
[:> numeric-input
|
||||
{:min 0
|
||||
:value (-> (:stroke-width values) width->string)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:on-change on-stroke-width-change}]]
|
||||
|
||||
[:select#style.input-select {:value (enum->string (:stroke-alignment values))
|
||||
:on-change on-stroke-alignment-change}
|
||||
|
|
|
@ -215,7 +215,7 @@
|
|||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect 1"})
|
||||
{:name "Rect-1"})
|
||||
(thp/make-component :instance1
|
||||
[(thp/id :shape1)]))
|
||||
|
||||
|
@ -247,8 +247,7 @@
|
|||
new-state
|
||||
new-component-id)]
|
||||
|
||||
(t/is (= (:name component2)
|
||||
"Component-2")))))
|
||||
(t/is (= (:name component2) "Rect-2")))))
|
||||
|
||||
(rx/subs done #(throw %))))))
|
||||
|
||||
|
@ -292,7 +291,7 @@
|
|||
(let [state (-> thp/initial-state
|
||||
(thp/sample-page)
|
||||
(thp/sample-shape :shape1 :rect
|
||||
{:name "Rect 1"})
|
||||
{:name "Rect-1"})
|
||||
(thp/make-component :instance1
|
||||
[(thp/id :shape1)]))
|
||||
|
||||
|
@ -320,10 +319,10 @@
|
|||
|
||||
(t/is (not= (:id instance1) (:id instance2)))
|
||||
(t/is (= (:id component) component-id))
|
||||
(t/is (= (:name instance2) "Component-2"))
|
||||
(t/is (= (:name shape2) "Rect 1"))
|
||||
(t/is (= (:name c-instance2) "Component-1"))
|
||||
(t/is (= (:name c-shape2) "Rect 1")))))
|
||||
(t/is (= (:name instance2) "Rect-3"))
|
||||
(t/is (= (:name shape2) "Rect-1"))
|
||||
(t/is (= (:name c-instance2) "Rect-2"))
|
||||
(t/is (= (:name c-shape2) "Rect-1")))))
|
||||
|
||||
(rx/subs done #(throw %))))))
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue