mirror of
https://github.com/penpot/penpot.git
synced 2025-04-09 21:41:23 -05:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
a64cb47afb
21 changed files with 81 additions and 45 deletions
|
@ -111,6 +111,8 @@
|
|||
- Fix 400 error when user changes password [Taiga #5643](https://tree.taiga.io/project/penpot/issue/5643)
|
||||
- Fix cannot undo layer styles [Taiga #5676](https://tree.taiga.io/project/penpot/issue/5676)
|
||||
- Fix unexpected exception on boolean shapes [Taiga #5685](https://tree.taiga.io/project/penpot/issue/5685)
|
||||
- Fix ctrl+z on select not working [Taiga #5677](https://tree.taiga.io/project/penpot/issue/5677)
|
||||
- Fix thubmnail rendering flashing [Taiga #5675](https://tree.taiga.io/project/penpot/issue/5675)
|
||||
|
||||
### :arrow_up: Deps updates
|
||||
|
||||
|
|
|
@ -1,36 +1,30 @@
|
|||
[{:id "material-design-3"
|
||||
:name "Material Design 3"
|
||||
:thumbnail-uri "https://penpot.app/images/libraries/cover-md3.jpg"
|
||||
:file-uri "https://github.com/penpot/penpot-files/raw/main/Material%20Design%203.penpot"}
|
||||
{:id "tutorial-for-beginners"
|
||||
:name "Tutorial for beginners"
|
||||
:thumbnail-uri "https://penpot.app/images/libraries/tutorial-for-beginners.jpg"
|
||||
:file-uri "https://github.com/penpot/penpot-files/raw/binary-files/tutorial-for-beginners.penpot"}
|
||||
{:id "penpot-design-system"
|
||||
:name "Penpot Design System"
|
||||
:thumbnail-uri "https://penpot.app/images/libraries/cover-ds-penpot.jpg"
|
||||
:file-uri "https://github.com/penpot/penpot-files/raw/binary-files/Penpot-Design-system.penpot"}
|
||||
{:id "flex-layout-playground"
|
||||
:name "Flex Layout Playground"
|
||||
:file-uri "https://github.com/penpot/penpot-files/raw/main/Flex%20Layout%20Playground.penpot"}
|
||||
{:id "wireframing-kit"
|
||||
:name "Wireframing Kit"
|
||||
:thumbnail-uri "https://penpot.app/images/libraries/cover-wireframes.jpg"
|
||||
:file-uri "https://github.com/penpot/penpot-files/raw/binary-files/wireframing-kit.penpot"}
|
||||
{:id "ant-design"
|
||||
:name "Ant Design UI Kit (lite)"
|
||||
:thumbnail-uri "https://penpot.app/images/libraries/cover-ant-design.jpg"
|
||||
:file-uri "https://github.com/penpot/penpot-files/raw/binary-files/Ant-Design-UI-Kit-Lite.penpot"}
|
||||
{:id "cocomaterial"
|
||||
:name "Cocomaterial"
|
||||
:thumbnail-uri "https://penpot.app/images/libraries/cover-cocomaterial.jpg"
|
||||
:file-uri "https://github.com/penpot/penpot-files/raw/binary-files/Cocomaterial.penpot"}
|
||||
{:id "circum-icons"
|
||||
:name "Circum Icons pack"
|
||||
:thumbnail-uri "https://penpot.app/images/libraries/cover-circum.jpg"
|
||||
:file-uri "https://github.com/penpot/penpot-files/raw/binary-files/CircumIcons.penpot"}
|
||||
{:id "coreui"
|
||||
:name "CoreUI"
|
||||
:thumbnail-uri "https://penpot.app/images/libraries/cover-coreui.jpg"
|
||||
:file-uri "https://github.com/penpot/penpot-files/raw/main/CoreUI%20DesignSystem%20(DEMO).penpot"}
|
||||
{:id "whiteboarding-kit"
|
||||
:name "Whiteboarding Kit"
|
||||
:thumbnail-uri "https://penpot.app/images/libraries/cover-whiteboards.jpg"
|
||||
:file-uri "https://github.com/penpot/penpot-files/raw/binary-files/Whiteboarding-mapping-kit.penpot"}]
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[clojure.spec.alpha :as s]
|
||||
[clojure.walk :as walk]))
|
||||
[clojure.walk :as walk]
|
||||
[promesa.exec :as px]))
|
||||
|
||||
;; --- COMMAND: Duplicate File
|
||||
|
||||
|
@ -322,6 +323,18 @@
|
|||
;; delete possible broken relations on moved files
|
||||
(db/exec-one! conn [sql:delete-broken-relations pids])
|
||||
|
||||
;; Update the modification date of the all affected projects
|
||||
;; ensuring that the destination project is the most recent one.
|
||||
(doseq [project-id (into (list project-id) source)]
|
||||
|
||||
;; NOTE: as this is executed on virtual thread, sleeping does
|
||||
;; not causes major issues, and allows an easy way to set a
|
||||
;; trully different modification date to each file.
|
||||
(px/sleep 10)
|
||||
(db/update! conn :project
|
||||
{:modified-at (dt/now)}
|
||||
{:id project-id}))
|
||||
|
||||
nil))
|
||||
|
||||
(s/def ::ids (s/every ::us/uuid :kind set?))
|
||||
|
@ -423,9 +436,9 @@
|
|||
{::doc/added "1.10"
|
||||
::doc/deprecated "1.19"}
|
||||
[cfg _params]
|
||||
(mapv #(select-keys % [:id :name :thumbnail-uri]) (::setup/templates cfg)))
|
||||
(mapv #(select-keys % [:id :name]) (::setup/templates cfg)))
|
||||
|
||||
(sv/defmethod ::get-builtin-templates
|
||||
{::doc/added "1.19"}
|
||||
[cfg _params]
|
||||
(mapv #(select-keys % [:id :name :thumbnail-uri]) (::setup/templates cfg)))
|
||||
(mapv #(select-keys % [:id :name]) (::setup/templates cfg)))
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
[:map {:title "Template"}
|
||||
[:id ::sm/word-string]
|
||||
[:name ::sm/word-string]
|
||||
[:thumbnail-uri ::sm/word-string]
|
||||
[:file-uri ::sm/word-string]])
|
||||
|
||||
(def ^:private schema:templates
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 51 KiB |
|
@ -10,7 +10,6 @@
|
|||
[app.common.data.macros :as dm]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as dt]
|
||||
[app.common.uri :as u]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
|
@ -23,6 +22,7 @@
|
|||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.router :as rt]
|
||||
[app.util.time :as dt]
|
||||
[app.util.timers :as tm]
|
||||
[app.util.webapi :as wapi]
|
||||
[beicon.core :as rx]
|
||||
|
@ -863,6 +863,7 @@
|
|||
[{:keys [ids project-id] :as params}]
|
||||
(dm/assert! (sm/set-of-uuid? ids))
|
||||
(dm/assert! (uuid? project-id))
|
||||
|
||||
(ptk/reify ::move-files
|
||||
IDeref
|
||||
(-deref [_]
|
||||
|
@ -872,13 +873,13 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [origin-project (get-in state [:dashboard-files (first ids) :project-id])
|
||||
update-project (fn [project]
|
||||
update-project (fn [project delta]
|
||||
(-> project
|
||||
(update :count #(+ % (count ids)))
|
||||
(assoc :modified-at (dt/now))))]
|
||||
(assoc :modified-at (dt/plus (dt/now) {:milliseconds delta}))))]
|
||||
(-> state
|
||||
(d/update-in-when [:dashboard-projects origin-project] update-project)
|
||||
(d/update-in-when [:dashboard-projects project-id] update-project))))
|
||||
(d/update-in-when [:dashboard-projects origin-project] update-project 0)
|
||||
(d/update-in-when [:dashboard-projects project-id] update-project 10))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
|
|
|
@ -17,17 +17,20 @@ if (Mousetrap.addKeycodes) {
|
|||
|
||||
const target = Mousetrap.prototype || Mousetrap;
|
||||
target.stopCallback = function(e, element, combo) {
|
||||
// if the element has the class "mousetrap" then no need to stop
|
||||
if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {
|
||||
return false;
|
||||
// if the element has the data attribute "mousetrap-dont-stop" then no need
|
||||
// to stop. It should be used like <div data-mousetrap-dont-stop>...</div>
|
||||
// or :div {:data-mousetrap-dont-stop true}
|
||||
if ('mousetrapDontStop' in element.dataset) {
|
||||
return false
|
||||
}
|
||||
|
||||
// stop for input, select, textarea and button
|
||||
return element.tagName == 'INPUT' ||
|
||||
element.tagName == 'SELECT' ||
|
||||
element.tagName == 'TEXTAREA' ||
|
||||
(element.tagName == 'BUTTON' && combo.includes("tab")) ||
|
||||
(element.contentEditable && element.contentEditable == 'true');
|
||||
const shouldStop = element.tagName == "INPUT" ||
|
||||
element.tagName == "SELECT" ||
|
||||
element.tagName == "TEXTAREA" ||
|
||||
(element.tagName == "BUTTON" && combo.includes("tab")) ||
|
||||
(element.contentEditable && element.contentEditable == "true");
|
||||
return shouldStop;
|
||||
}
|
||||
|
||||
export default Mousetrap;
|
||||
|
|
|
@ -296,10 +296,9 @@
|
|||
:on-import on-import}]
|
||||
|
||||
[:span.info (str (tr "labels.num-of-files" (i18n/c file-count)))]
|
||||
(when (> file-count 0)
|
||||
(let [time (-> (:modified-at project)
|
||||
(dt/timeago {:locale locale}))]
|
||||
[:span.recent-files-row-title-info (str ", " time)]))
|
||||
(let [time (-> (:modified-at project)
|
||||
(dt/timeago {:locale locale}))]
|
||||
[:span.recent-files-row-title-info (str ", " time)])
|
||||
[:div.project-actions
|
||||
(when-not (:is-default project)
|
||||
[:button.pin-icon.tooltip.tooltip-bottom
|
||||
|
|
|
@ -150,8 +150,9 @@
|
|||
(mf/defc templates-section
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [default-project-id profile project-id team-id content-width]}]
|
||||
(let [templates (->> (mf/deref builtin-templates)
|
||||
(filter #(not= (:id %) "tutorial-for-beginners")))
|
||||
(let [templates (mf/deref builtin-templates)
|
||||
templates (mf/with-memo [templates]
|
||||
(filterv #(not= (:id %) "tutorial-for-beginners") templates))
|
||||
|
||||
route (mf/deref refs/route)
|
||||
route-name (get-in route [:data :name])
|
||||
|
|
|
@ -72,7 +72,9 @@
|
|||
(reset! current-colors (into [] (filter check-valid-color?) colors)))))
|
||||
|
||||
[:div.libraries
|
||||
[:select {:on-change on-library-change :value (name @selected)}
|
||||
[:select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:on-change on-library-change
|
||||
:value (name @selected)}
|
||||
[:option {:value "recent"} (tr "workspace.libraries.colors.recent-colors")]
|
||||
[:option {:value "file"} (tr "workspace.libraries.colors.file-library")]
|
||||
|
||||
|
|
|
@ -103,7 +103,6 @@
|
|||
render-frame* (mf/use-state (not thumbnail-uri))
|
||||
debug? (debug? :thumbnails)
|
||||
|
||||
|
||||
on-bitmap-load
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
|
@ -171,6 +170,8 @@
|
|||
(when (not= "false" (dom/get-data image-node "ready"))
|
||||
(dom/set-data! image-node "ready" "false")))
|
||||
(when-not ^boolean @disable*
|
||||
(reset! svg-uri* nil)
|
||||
(reset! bitmap-uri* nil)
|
||||
(reset! render-frame* true)
|
||||
(reset! regenerate* true))))
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@
|
|||
(if ^boolean new-css-system
|
||||
[:div {:class (css :assets-bar)}
|
||||
[:div {:class (css :assets-header)}
|
||||
(when-not read-only?
|
||||
(when-not ^boolean read-only?
|
||||
[:button {:class (css :libraries-button)
|
||||
:on-click #(modal/show! :libraries-dialog {})}
|
||||
[:span {:class (css :libraries-icon)}
|
||||
|
@ -229,6 +229,7 @@
|
|||
i/close])]
|
||||
|
||||
[:select.input-select {:value (:section filters)
|
||||
:data-mousetrap-dont-stop true
|
||||
:on-change on-section-filter-change}
|
||||
[:option {:value "all"} (tr "workspace.assets.box-filter-all")]
|
||||
[:option {:value "components"} (tr "workspace.assets.components")]
|
||||
|
|
|
@ -189,7 +189,7 @@
|
|||
;; NOTE: Neither get-parent-at nor get-parent-with-selector
|
||||
;; work if the component template changes, so we need to
|
||||
;; seek for an alternate solution. Maybe use-context?
|
||||
scroll-node (dom/get-parent-with-selector node ".tool-window-content")
|
||||
scroll-node (dom/get-parent-with-data node "scrollContainer")
|
||||
parent-node (dom/get-parent-at node 2)
|
||||
|
||||
subid
|
||||
|
|
|
@ -538,6 +538,7 @@
|
|||
(if (some? filtered-objects)
|
||||
[:*
|
||||
[:div {:class (stl/css new-css-system :tool-window-content)
|
||||
:data-scroll-container true
|
||||
:ref on-render-container}
|
||||
[:& filters-tree {:objects filtered-objects
|
||||
:key (dm/str (:id page))
|
||||
|
@ -546,6 +547,7 @@
|
|||
:style {:min-height 16}}]]
|
||||
[:div {:on-scroll on-scroll
|
||||
:class (stl/css new-css-system :tool-window-content)
|
||||
:data-scroll-container true
|
||||
:style {:display (when (some? filtered-objects) "none")}}
|
||||
[:& layers-tree {:objects filtered-objects
|
||||
:key (dm/str (:id page))
|
||||
|
@ -554,6 +556,7 @@
|
|||
|
||||
[:div {:on-scroll on-scroll
|
||||
:class (stl/css new-css-system :tool-window-content)
|
||||
:data-scroll-container true
|
||||
:style {:display (when (some? filtered-objects) "none")}}
|
||||
[:& layers-tree {:objects objects
|
||||
:key (dm/str (:id page))
|
||||
|
|
|
@ -147,7 +147,8 @@
|
|||
[:div.constraints-form
|
||||
[:div.row-flex
|
||||
[:span.left-right i/full-screen]
|
||||
[:select.input-select {:on-change (on-constraint-select-changed :constraints-h)
|
||||
[:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:on-change (on-constraint-select-changed :constraints-h)
|
||||
:value (d/name constraints-h "scale")}
|
||||
(when (= constraints-h :multiple)
|
||||
[:option {:value ""} (tr "settings.multiple")])
|
||||
|
@ -158,7 +159,8 @@
|
|||
[:option {:value "scale"} (tr "workspace.options.constraints.scale")]]]
|
||||
[:div.row-flex
|
||||
[:span.top-bottom i/full-screen]
|
||||
[:select.input-select {:on-change (on-constraint-select-changed :constraints-v)
|
||||
[:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:on-change (on-constraint-select-changed :constraints-v)
|
||||
:value (d/name constraints-v "scale")}
|
||||
(when (= constraints-v :multiple)
|
||||
[:option {:value ""} (tr "settings.multiple")])
|
||||
|
|
|
@ -169,7 +169,8 @@
|
|||
[:div.element-set-options-group
|
||||
{:key index}
|
||||
(when (scale-enabled? export)
|
||||
[:select.input-select {:on-change (partial on-scale-change index)
|
||||
[:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:on-change (partial on-scale-change index)
|
||||
:value (:scale export)}
|
||||
[:option {:value "0.5"} "0.5x"]
|
||||
[:option {:value "0.75"} "0.75x"]
|
||||
|
@ -182,7 +183,8 @@
|
|||
:placeholder (tr "workspace.options.export.suffix")
|
||||
:on-change (partial on-suffix-change index)
|
||||
:on-key-down manage-key-down}]
|
||||
[:select.input-select {:value (d/name (:type export))
|
||||
[:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:value (d/name (:type export))
|
||||
:on-change (partial on-type-change index)}
|
||||
[:option {:value "png"} "PNG"]
|
||||
[:option {:value "jpeg"} "JPEG"]
|
||||
|
|
|
@ -139,7 +139,8 @@
|
|||
i/actions]
|
||||
|
||||
[:select.input-select
|
||||
{:default-value shadow-style
|
||||
{:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:default-value shadow-style
|
||||
:on-change (fn [event]
|
||||
(let [value (-> event dom/get-target dom/get-value d/read-string)]
|
||||
(st/emit! (dch/update-shapes ids #(assoc-in % [:shadow index :style] value)))))}
|
||||
|
@ -165,7 +166,8 @@
|
|||
{:on-click on-toggle-open-shadow}
|
||||
i/actions]
|
||||
[:select.input-select
|
||||
{:default-value shadow-style
|
||||
{:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:default-value shadow-style
|
||||
:on-change (fn [event]
|
||||
(let [value (-> event dom/get-target dom/get-value d/read-string)]
|
||||
(st/emit! (dch/update-shapes ids #(assoc-in % [:shadow index :style] value)))))}
|
||||
|
|
|
@ -425,6 +425,7 @@
|
|||
|
||||
[:select.input-select.variant-option
|
||||
{:disabled (= font-id :multiple)
|
||||
:data-mousetrap-dont-stop true
|
||||
:value (attr->string font-variant-id)
|
||||
:on-change on-font-variant-change
|
||||
:on-blur on-blur}
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
|
||||
(case type
|
||||
:select
|
||||
[:& select {:default-value value
|
||||
[:& select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:default-value value
|
||||
:class "input-option"
|
||||
:options options
|
||||
:on-change on-change}]
|
||||
|
|
|
@ -106,7 +106,8 @@
|
|||
:select-on-focus select-on-focus
|
||||
:on-blur on-blur}]]
|
||||
|
||||
[:select#style.input-select {:value (enum->string (:stroke-alignment stroke))
|
||||
[:select#style.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:value (enum->string (:stroke-alignment stroke))
|
||||
:on-change (on-stroke-alignment-change index)}
|
||||
(when (= (:stroke-alignment stroke) :multiple)
|
||||
[:option {:value ""} "--"])
|
||||
|
@ -115,7 +116,8 @@
|
|||
[:option {:value ":outer"} (tr "workspace.options.stroke.outer")]]
|
||||
|
||||
(when-not disable-stroke-style
|
||||
[:select#style.input-select {:value (enum->string (:stroke-style stroke))
|
||||
[:select#style.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:value (enum->string (:stroke-style stroke))
|
||||
:on-change (on-stroke-style-change index)}
|
||||
(when (= (:stroke-style stroke) :multiple)
|
||||
[:option {:value ""} "--"])
|
||||
|
|
|
@ -166,6 +166,13 @@
|
|||
current
|
||||
(recur (.-parentElement current) (dec current-count))))))
|
||||
|
||||
(defn get-parent-with-data
|
||||
[^js node name]
|
||||
(loop [current node]
|
||||
(if (or (nil? current) (obj/in? (.-dataset current) name))
|
||||
current
|
||||
(recur (.-parentElement current)))))
|
||||
|
||||
(defn get-parent-with-selector
|
||||
[^js node selector]
|
||||
(loop [current node]
|
||||
|
|
Loading…
Add table
Reference in a new issue