mirror of
https://github.com/penpot/penpot.git
synced 2025-06-13 10:51:38 +02:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
a25f069f8e
61 changed files with 1003 additions and 594 deletions
|
@ -1969,3 +1969,6 @@
|
|||
(dm/export dwv/update-viewport-size)
|
||||
(dm/export dwv/start-panning)
|
||||
(dm/export dwv/finish-panning)
|
||||
|
||||
;; Undo
|
||||
(dm/export dwu/reinitialize-undo)
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
(->> (rx/from uris)
|
||||
(rx/filter (comp not svg-url?))
|
||||
(rx/map prepare)
|
||||
(rx/mapcat #(rp/mutation! :create-file-media-object-from-url %))
|
||||
(rx/mapcat #(rp/command! :create-file-media-object-from-url %))
|
||||
(rx/do on-image))
|
||||
|
||||
(->> (rx/from uris)
|
||||
|
|
|
@ -114,6 +114,18 @@
|
|||
|
||||
(reduce set-child ignore-tree children))))
|
||||
|
||||
(defn assoc-position-data
|
||||
[shape position-data old-shape]
|
||||
(let [deltav (gpt/to-vec (gpt/point (:selrect old-shape))
|
||||
(gpt/point (:selrect shape)))
|
||||
position-data
|
||||
(-> position-data
|
||||
(gsh/move-position-data deltav))]
|
||||
(cond-> shape
|
||||
(d/not-empty? position-data)
|
||||
(assoc :position-data position-data))))
|
||||
|
||||
|
||||
(defn update-grow-type
|
||||
[shape old-shape]
|
||||
(let [auto-width? (= :auto-width (:grow-type shape))
|
||||
|
@ -319,7 +331,8 @@
|
|||
(ptk/reify ::apply-modifiers
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [text-modifiers (get state :workspace-text-modifier)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
object-modifiers (if modifiers
|
||||
(calculate-modifiers state modifiers)
|
||||
(get state :workspace-modifiers))
|
||||
|
@ -342,9 +355,13 @@
|
|||
ids
|
||||
(fn [shape]
|
||||
(let [modif (get-in object-modifiers [(:id shape) :modifiers])
|
||||
text-shape? (cph/text-shape? shape)]
|
||||
text-shape? (cph/text-shape? shape)
|
||||
position-data (when text-shape?
|
||||
(dm/get-in text-modifiers [(:id shape) :position-data]))]
|
||||
(-> shape
|
||||
(gsh/transform-shape modif)
|
||||
(cond-> (d/not-empty? position-data)
|
||||
(assoc-position-data position-data shape))
|
||||
(cond-> text-shape?
|
||||
(update-grow-type shape)))))
|
||||
{:reg-objects? true
|
||||
|
@ -366,7 +383,11 @@
|
|||
:grow-type
|
||||
:layout-item-h-sizing
|
||||
:layout-item-v-sizing
|
||||
:position-data
|
||||
]})
|
||||
;; We've applied the text-modifier so we can dissoc the temporary data
|
||||
(fn [state]
|
||||
(update state :workspace-text-modifier #(apply dissoc % ids)))
|
||||
(clear-local-transform))
|
||||
(if undo-transation?
|
||||
(rx/of (dwu/commit-undo-transaction undo-id))
|
||||
|
|
|
@ -466,9 +466,10 @@
|
|||
{:name (extract-name uri)
|
||||
:url uri}))))
|
||||
(rx/mapcat (fn [uri-data]
|
||||
(->> (rp/mutation! (if (contains? uri-data :content)
|
||||
:upload-file-media-object
|
||||
:create-file-media-object-from-url) uri-data)
|
||||
(->> (rp/command! (if (contains? uri-data :content)
|
||||
:upload-file-media-object
|
||||
:create-file-media-object-from-url)
|
||||
uri-data)
|
||||
;; When the image uploaded fail we skip the shape
|
||||
;; returning `nil` will afterward not create the shape.
|
||||
(rx/catch #(rx/of nil))
|
||||
|
|
|
@ -344,7 +344,7 @@
|
|||
(when (or (and (not-changed? (:width shape) new-width) (= (:grow-type shape) :auto-width))
|
||||
(and (not-changed? (:height shape) new-height)
|
||||
(or (= (:grow-type shape) :auto-height) (= (:grow-type shape) :auto-width))))
|
||||
(rx/of (dch/update-shapes [id] update-fn {:reg-objects? true :save-undo? false})
|
||||
(rx/of (dch/update-shapes [id] update-fn {:reg-objects? true :save-undo? true})
|
||||
(ptk/data-event :layout/update [id]))))))))
|
||||
|
||||
|
||||
|
@ -377,7 +377,7 @@
|
|||
(gpt/point (:selrect shape)))
|
||||
|
||||
new-shape
|
||||
(update new-shape :position-data gsh/move-position-data (:x delta-move) (:y delta-move))]
|
||||
(update new-shape :position-data gsh/move-position-data delta-move)]
|
||||
|
||||
new-shape))
|
||||
|
||||
|
|
|
@ -86,7 +86,8 @@
|
|||
(dom/blur! input-node)))
|
||||
(when esc?
|
||||
(dom/prevent-default event)
|
||||
(update-input value)))))
|
||||
(update-input value)
|
||||
(dom/blur! input-node)))))
|
||||
|
||||
handle-blur
|
||||
(mf/use-callback
|
||||
|
|
|
@ -163,7 +163,8 @@
|
|||
(when enter?
|
||||
(dom/blur! input-node))
|
||||
(when esc?
|
||||
(update-input value-str)))))
|
||||
(update-input value-str)
|
||||
(dom/blur! input-node)))))
|
||||
|
||||
handle-mouse-wheel
|
||||
(mf/use-callback
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
(when (> (count items) 0)
|
||||
[:*
|
||||
[:p (tr "ds.component-subtitle")]
|
||||
[:ul
|
||||
[:ul.component-list
|
||||
(for [item items]
|
||||
[:li.modal-item-element
|
||||
[:span.modal-component-icon i/component]
|
||||
|
|
|
@ -407,7 +407,7 @@
|
|||
[:& interface-walkthrough
|
||||
{:close-walkthrough close-walkthrough}])])
|
||||
|
||||
[:div.dashboard-container.no-bg
|
||||
[:div.dashboard-container.no-bg.dashboard-projects
|
||||
(for [{:keys [id] :as project} projects]
|
||||
(let [files (when recent-map
|
||||
(->> (vals recent-map)
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
(when-not (:gradient color) [:div (str (* 100 (:opacity color)) "%")])]))
|
||||
|
||||
(when-not (and on-change-format (:gradient color))
|
||||
[:select {:on-change #(-> (dom/get-target-val %) keyword on-change-format)}
|
||||
[:select.color-format-select {:on-change #(-> (dom/get-target-val %) keyword on-change-format)}
|
||||
[:option {:value "hex"}
|
||||
(tr "inspect.attributes.color.hex")]
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
[app.main.ui.workspace.libraries]
|
||||
[app.main.ui.workspace.nudge]
|
||||
[app.main.ui.workspace.sidebar :refer [left-sidebar right-sidebar]]
|
||||
[app.main.ui.workspace.sidebar.history :refer [history-toolbox]]
|
||||
[app.main.ui.workspace.textpalette :refer [textpalette]]
|
||||
[app.main.ui.workspace.viewport :refer [viewport]]
|
||||
[app.util.dom :as dom]
|
||||
|
@ -72,6 +73,10 @@
|
|||
(when (debug? :coordinates)
|
||||
[:& coordinates/coordinates {:colorpalette? colorpalette?}])
|
||||
|
||||
(when (debug? :history-overlay)
|
||||
[:div.history-debug-overlay
|
||||
[:button {:on-click #(st/emit! dw/reinitialize-undo)} "CLEAR"]
|
||||
[:& history-toolbox]])
|
||||
[:& viewport {:file file
|
||||
:wlocal wlocal
|
||||
:wglobal wglobal
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.keyboard :as kbd]
|
||||
[app.util.strings :refer [matches-search]]
|
||||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
|
@ -93,11 +94,22 @@
|
|||
(st/emit! (modal/show
|
||||
{:type :delete-shared
|
||||
:origin :unpublish
|
||||
:on-accept (fn[]
|
||||
:on-accept (fn []
|
||||
(st/emit! (dwl/set-file-shared (:id file) false))
|
||||
(modal/show! :libraries-dialog {}))
|
||||
:on-cancel #(modal/show! :libraries-dialog {})
|
||||
:count-libraries 1}))))]
|
||||
:count-libraries 1}))))
|
||||
handle-key-down
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(let [enter? (kbd/enter? event)
|
||||
esc? (kbd/esc? event)
|
||||
input-node (dom/event->target event)]
|
||||
|
||||
(when enter?
|
||||
(dom/blur! input-node))
|
||||
(when esc?
|
||||
(dom/blur! input-node)))))]
|
||||
[:*
|
||||
[:div.section
|
||||
[:div.section-title (tr "workspace.libraries.in-this-file")]
|
||||
|
@ -130,7 +142,8 @@
|
|||
{:placeholder (tr "workspace.libraries.search-shared-libraries")
|
||||
:type "text"
|
||||
:value @search-term
|
||||
:on-change on-search-term-change}]
|
||||
:on-change on-search-term-change
|
||||
:on-key-down handle-key-down}]
|
||||
(if (str/empty? @search-term)
|
||||
[:div.search-icon
|
||||
i/search]
|
||||
|
|
|
@ -140,6 +140,10 @@
|
|||
(let [text-shapes (obj/get props "text-shapes")
|
||||
prev-text-shapes (hooks/use-previous text-shapes)
|
||||
|
||||
;; We store in the state the texts still pending to be calculated so we can
|
||||
;; get its position
|
||||
pending-update (mf/use-state {})
|
||||
|
||||
text-change?
|
||||
(fn [id]
|
||||
(let [new-shape (get text-shapes id)
|
||||
|
@ -153,12 +157,23 @@
|
|||
|
||||
changed-texts
|
||||
(mf/use-memo
|
||||
(mf/deps text-shapes)
|
||||
#(->> (keys text-shapes)
|
||||
(filter text-change?)
|
||||
(map (d/getf text-shapes))))
|
||||
(mf/deps text-shapes @pending-update)
|
||||
#(let [pending-shapes (into #{} (vals @pending-update))]
|
||||
(->> (keys text-shapes)
|
||||
(filter (fn [id]
|
||||
(or (contains? pending-shapes id)
|
||||
(text-change? id))))
|
||||
(map (d/getf text-shapes)))))
|
||||
|
||||
handle-update-shape (mf/use-callback update-text-shape)]
|
||||
handle-update-shape
|
||||
(mf/use-callback
|
||||
(fn [shape node]
|
||||
;; Unique to indentify the pending state
|
||||
(let [uid (js/Symbol)]
|
||||
(swap! pending-update assoc uid (:id shape))
|
||||
(p/then
|
||||
(update-text-shape shape node)
|
||||
#(swap! pending-update dissoc uid)))))]
|
||||
|
||||
[:.text-changes-renderer
|
||||
(for [{:keys [id] :as shape} changed-texts]
|
||||
|
|
|
@ -2243,7 +2243,19 @@
|
|||
(let [value (-> (dom/get-target event)
|
||||
(dom/get-value)
|
||||
(d/read-string))]
|
||||
(swap! filters assoc :box value))))]
|
||||
(swap! filters assoc :box value))))
|
||||
|
||||
handle-key-down
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(let [enter? (kbd/enter? event)
|
||||
esc? (kbd/esc? event)
|
||||
input-node (dom/event->target event)]
|
||||
|
||||
(when enter?
|
||||
(dom/blur! input-node))
|
||||
(when esc?
|
||||
(dom/blur! input-node)))))]
|
||||
|
||||
[:div.assets-bar
|
||||
[:div.tool-window
|
||||
|
@ -2260,7 +2272,8 @@
|
|||
{:placeholder (tr "workspace.assets.search")
|
||||
:type "text"
|
||||
:value (:term @filters)
|
||||
:on-change on-search-term-change}]
|
||||
:on-change on-search-term-change
|
||||
:on-key-down handle-key-down}]
|
||||
(if (str/empty? (:term @filters))
|
||||
[:div.search-icon
|
||||
i/search]
|
||||
|
|
|
@ -468,7 +468,19 @@
|
|||
handle-show-more
|
||||
(fn []
|
||||
(when (<= (:num-items @filter-state) (count filtered-objects-total))
|
||||
(swap! filter-state update :num-items + 100)))]
|
||||
(swap! filter-state update :num-items + 100)))
|
||||
|
||||
handle-key-down
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(let [enter? (kbd/enter? event)
|
||||
esc? (kbd/esc? event)
|
||||
input-node (dom/event->target event)]
|
||||
|
||||
(when enter?
|
||||
(dom/blur! input-node))
|
||||
(when esc?
|
||||
(dom/blur! input-node)))))]
|
||||
|
||||
[filtered-objects
|
||||
handle-show-more
|
||||
|
@ -483,7 +495,8 @@
|
|||
[:input {:on-change update-search-text
|
||||
:value (:search-text @filter-state)
|
||||
:auto-focus (:show-search-box @filter-state)
|
||||
:placeholder (tr "workspace.sidebar.layers.search")}]]
|
||||
:placeholder (tr "workspace.sidebar.layers.search")
|
||||
:on-key-down handle-key-down}]]
|
||||
(when (not (= "" (:search-text @filter-state)))
|
||||
[:span.clear {:on-click clear-search-text} i/exclude])]
|
||||
[:span {:on-click toggle-search} i/cross]]
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :refer [tr c]]
|
||||
[app.util.keyboard :as kbd]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def exports-attrs
|
||||
|
@ -123,7 +124,13 @@
|
|||
(fn []
|
||||
(st/emit! (dch/update-shapes ids
|
||||
(fn [shape]
|
||||
(assoc shape :exports []))))))]
|
||||
(assoc shape :exports []))))))
|
||||
manage-key-down
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(let [esc? (kbd/esc? event)]
|
||||
(when esc?
|
||||
(dom/blur! (dom/get-target event))))))]
|
||||
|
||||
[:div.element-set.exports-options
|
||||
[:div.element-set-title
|
||||
|
@ -156,7 +163,8 @@
|
|||
[:option {:value "6"} "6x"]])
|
||||
[:input.input-text {:value (:suffix export)
|
||||
:placeholder (tr "workspace.options.export.suffix")
|
||||
:on-change (partial on-suffix-change index)}]
|
||||
:on-change (partial on-suffix-change index)
|
||||
:on-key-down manage-key-down}]
|
||||
[:select.input-select {:value (name (:type export))
|
||||
:on-change (partial on-type-change index)}
|
||||
[:option {:value "png"} "PNG"]
|
||||
|
|
|
@ -282,7 +282,8 @@
|
|||
(when (and (options :presets)
|
||||
(or (nil? all-types) (= (count all-types) 1))) ;; Don't show presets if multi selected
|
||||
[:div.row-flex ;; some frames and some non frames
|
||||
[:div.presets.custom-select.flex-grow {:on-click #(reset! show-presets-dropdown? true)}
|
||||
[:div.presets.custom-select.flex-grow {:class (when @show-presets-dropdown? "opened")
|
||||
:on-click #(reset! show-presets-dropdown? true)}
|
||||
[:span (tr "workspace.options.size-presets")]
|
||||
[:span.dropdown-button i/arrow-down]
|
||||
[:& dropdown {:show @show-presets-dropdown?
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.fonts :as fonts]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
|
@ -20,7 +21,7 @@
|
|||
[app.main.ui.workspace.sidebar.options.menus.typography :refer [typography-entry typography-options]]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.timers :as tm]
|
||||
[app.util.timers :as ts]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
|
@ -164,7 +165,12 @@
|
|||
(let [grow-type (:grow-type values)
|
||||
handle-change-grow
|
||||
(fn [_ grow-type]
|
||||
(st/emit! (dch/update-shapes ids #(assoc % :grow-type grow-type)))
|
||||
(let [uid (js/Symbol)]
|
||||
(st/emit!
|
||||
(dwu/start-undo-transaction uid)
|
||||
(dch/update-shapes ids #(assoc % :grow-type grow-type)))
|
||||
;; We asynchronously commit so every sychronous event is resolved first and inside the transaction
|
||||
(ts/schedule #(st/emit! (dwu/commit-undo-transaction uid))))
|
||||
(when (some? on-blur) (on-blur)))]
|
||||
|
||||
[:div.align-icons
|
||||
|
@ -304,7 +310,7 @@
|
|||
:show-recent true
|
||||
:on-blur
|
||||
(fn []
|
||||
(tm/schedule
|
||||
(ts/schedule
|
||||
100
|
||||
(fn []
|
||||
(when (not= "INPUT" (-> (dom/get-active) (dom/get-tag-name)))
|
||||
|
|
|
@ -225,7 +225,9 @@
|
|||
;; inside a foreign object "dummy" so this awkward behaviour is take into account
|
||||
[:svg {:style {:top 0 :left 0 :position "fixed" :width "100%" :height "100%" :opacity (when-not (debug? :html-text) 0)}}
|
||||
[:foreignObject {:x 0 :y 0 :width "100%" :height "100%"}
|
||||
[:div {:style {:pointer-events (when-not (debug? :html-text) "none")}}
|
||||
[:div {:style {:pointer-events (when-not (debug? :html-text) "none")
|
||||
;; some opacity because to debug auto-width events will fill the screen
|
||||
:opacity 0.6}}
|
||||
[:& stvh/viewport-texts
|
||||
{:key (dm/str "texts-" page-id)
|
||||
:page-id page-id
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue