mirror of
https://github.com/penpot/penpot.git
synced 2025-03-30 16:41:20 -05:00
commit
17d28ed9bc
13 changed files with 83 additions and 51 deletions
|
@ -95,8 +95,8 @@
|
|||
(defn- find-filename-candidate
|
||||
[params used]
|
||||
(loop [index 0]
|
||||
(let [candidate (str (str/slug (:name params))
|
||||
(str/trim (str/blank? (:suffix params "")))
|
||||
(let [candidate (str (:name params)
|
||||
(:suffix params "")
|
||||
(when (pos? index)
|
||||
(str "-" (inc index)))
|
||||
(case (:type params)
|
||||
|
|
|
@ -62,8 +62,8 @@
|
|||
(p/let [content (screenshot-object browser params)]
|
||||
{:content content
|
||||
:filename (or (:filename params)
|
||||
(str (str/slug (:name params))
|
||||
(str/trim (:suffix params ""))
|
||||
(str (:name params)
|
||||
(:suffix params "")
|
||||
(case (:type params)
|
||||
:png ".png"
|
||||
:jpeg ".jpg")))
|
||||
|
|
|
@ -261,8 +261,8 @@
|
|||
(p/let [content (render-object browser params)]
|
||||
{:content content
|
||||
:filename (or (:filename params)
|
||||
(str (str/slug (:name params))
|
||||
(str/trim (:suffix params ""))
|
||||
(str (:name params)
|
||||
(:suffix params "")
|
||||
".svg"))
|
||||
:length (alength content)
|
||||
:mime-type "image/svg+xml"}))
|
||||
|
|
|
@ -4092,10 +4092,10 @@
|
|||
"workspace.toolbar.path" : {
|
||||
"used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:98" ],
|
||||
"translations" : {
|
||||
"en" : "Path",
|
||||
"fr" : "Chemin",
|
||||
"ru" : "Линия",
|
||||
"es" : "Ruta"
|
||||
"en" : "Path (P)",
|
||||
"fr" : "Chemin (P)",
|
||||
"ru" : "Линия (P)",
|
||||
"es" : "Ruta (P)"
|
||||
}
|
||||
},
|
||||
"workspace.toolbar.rect" : {
|
||||
|
|
|
@ -277,7 +277,7 @@
|
|||
border-color: $color-black;
|
||||
}
|
||||
|
||||
.clear-search {
|
||||
.search, .clear-search {
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
|
@ -289,7 +289,6 @@
|
|||
svg {
|
||||
fill: $color-gray-30;
|
||||
height: 15px;
|
||||
transform: rotate(45deg);
|
||||
width: 15px;
|
||||
|
||||
&:hover {
|
||||
|
@ -297,6 +296,10 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.clear-search svg {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
}
|
||||
|
||||
&.profile-bar {
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
[{:keys [status body] :as response}]
|
||||
(cond
|
||||
(= 204 status)
|
||||
(rx/empty)
|
||||
;; We need to send "something" so the streams listening downstream can act
|
||||
(rx/of :empty)
|
||||
|
||||
(= 502 status)
|
||||
(rx/throw {:type :bad-gateway})
|
||||
|
|
|
@ -75,12 +75,14 @@
|
|||
(mf/defc sidebar-search
|
||||
[{:keys [search-term team-id locale] :as props}]
|
||||
(let [search-term (or search-term "")
|
||||
focused? (mf/use-state false)
|
||||
emit! (mf/use-memo #(f/debounce st/emit! 500))
|
||||
|
||||
on-search-focus
|
||||
(mf/use-callback
|
||||
(mf/deps team-id)
|
||||
(fn [event]
|
||||
(reset! focused? true)
|
||||
(let [target (dom/get-target event)
|
||||
value (dom/get-value target)]
|
||||
(dom/select-text! target)
|
||||
|
@ -88,6 +90,11 @@
|
|||
(emit! (rt/nav :dashboard-search {:team-id team-id} {}))
|
||||
(emit! (rt/nav :dashboard-search {:team-id team-id} {:search-term value}))))))
|
||||
|
||||
on-search-blur
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(reset! focused? false)))
|
||||
|
||||
on-search-change
|
||||
(mf/use-callback
|
||||
(mf/deps team-id)
|
||||
|
@ -114,11 +121,18 @@
|
|||
:default-value search-term
|
||||
:auto-complete "off"
|
||||
:on-focus on-search-focus
|
||||
:on-blur on-search-blur
|
||||
:on-change on-search-change
|
||||
:ref #(when % (set! (.-value %) search-term))}]
|
||||
[:div.clear-search
|
||||
{:on-click on-clear-click}
|
||||
i/close]]))
|
||||
|
||||
(if (or @focused? (not (empty? search-term)))
|
||||
[:div.clear-search
|
||||
{:on-click on-clear-click}
|
||||
i/close]
|
||||
|
||||
[:div.search
|
||||
{:on-click on-clear-click}
|
||||
i/search])]))
|
||||
|
||||
(mf/defc teams-selector-dropdown
|
||||
[{:keys [team profile locale] :as props}]
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[cuerdas.core :as str]
|
||||
[app.config :as cfg]
|
||||
[app.util.i18n :refer [t]]
|
||||
[app.util.dom :as dom]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.code-gen :as cg]
|
||||
[app.main.ui.components.copy-button :refer [copy-button]]))
|
||||
|
@ -20,18 +21,6 @@
|
|||
(defn has-image? [shape]
|
||||
(and (= (:type shape) :image)))
|
||||
|
||||
(defn mtype->extension [mtype]
|
||||
;; https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types
|
||||
(case mtype
|
||||
"image/apng" "apng"
|
||||
"image/avif" "avif"
|
||||
"image/gif" "gif"
|
||||
"image/jpeg" "jpg"
|
||||
"image/png" "png"
|
||||
"image/svg+xml" "svg"
|
||||
"image/webp" "webp"
|
||||
nil))
|
||||
|
||||
(mf/defc image-panel [{:keys [shapes locale]}]
|
||||
(let [shapes (->> shapes (filter has-image?))]
|
||||
(for [shape shapes]
|
||||
|
@ -52,7 +41,7 @@
|
|||
|
||||
(let [mtype (-> shape :metadata :mtype)
|
||||
name (:name shape)
|
||||
extension (mtype->extension mtype)]
|
||||
extension (dom/mtype->extension mtype)]
|
||||
[:a.download-button {:target "_blank"
|
||||
:download (if extension
|
||||
(str name "." extension)
|
||||
|
|
|
@ -205,21 +205,22 @@
|
|||
(let [center-x (+ x1 (/ (- x2 x1) 2))
|
||||
center-y (+ y1 (/ (- y2 y1) 2))
|
||||
distance (gpt/distance (gpt/point x1 y1) (gpt/point x2 y2))]
|
||||
[:g.distance-line {:key (str "line-%s-%s-%s-%s" x1 y1 x2 y2)}
|
||||
[:line
|
||||
{:x1 x1
|
||||
:y1 y1
|
||||
:x2 x2
|
||||
:y2 y2
|
||||
:style {:stroke distance-color
|
||||
:stroke-width distance-line-stroke}}]
|
||||
(when-not (mth/almost-zero? distance)
|
||||
[:g.distance-line {:key (str "line-%s-%s-%s-%s" x1 y1 x2 y2)}
|
||||
[:line
|
||||
{:x1 x1
|
||||
:y1 y1
|
||||
:x2 x2
|
||||
:y2 y2
|
||||
:style {:stroke distance-color
|
||||
:stroke-width distance-line-stroke}}]
|
||||
|
||||
[:& distance-display-pill
|
||||
{:x center-x
|
||||
:y center-y
|
||||
:zoom zoom
|
||||
:distance (str (mth/round distance) "px")
|
||||
:bounds bounds}]]))))
|
||||
[:& distance-display-pill
|
||||
{:x center-x
|
||||
:y center-y
|
||||
:zoom zoom
|
||||
:distance (str (mth/round distance) "px")
|
||||
:bounds bounds}]])))))
|
||||
|
||||
(mf/defc selection-guides [{:keys [bounds selrect zoom]}]
|
||||
[:g.selection-guides
|
||||
|
@ -233,11 +234,12 @@
|
|||
:stroke-dasharray (/ select-guide-dasharray zoom)}}])])
|
||||
|
||||
(mf/defc measurement [{:keys [bounds frame selected-shapes hover-shape zoom]}]
|
||||
(let [selected-selrect (gsh/selection-rect selected-shapes)
|
||||
(let [selected-ids (into #{} (map :id) selected-shapes)
|
||||
selected-selrect (gsh/selection-rect selected-shapes)
|
||||
hover-selrect (:selrect hover-shape)
|
||||
bounds-selrect (bound->selrect bounds)]
|
||||
|
||||
(when (seq selected-shapes)
|
||||
(when (and (seq selected-shapes) (not (contains? selected-ids (:id hover-shape))))
|
||||
[:g.measurement-feedback {:pointer-events "none"}
|
||||
[:& selection-guides {:selrect selected-selrect :bounds bounds :zoom zoom}]
|
||||
[:& size-display {:selrect selected-selrect :zoom zoom}]
|
||||
|
|
|
@ -115,7 +115,9 @@
|
|||
(let [shape (unchecked-get props "shape")
|
||||
grow-type (unchecked-get props "grow-type")
|
||||
embed-fonts? (mf/use-ctx muc/embed-ctx)
|
||||
{:keys [id x y width height content]} shape]
|
||||
{:keys [id x y width height content]} shape
|
||||
;; We add 8px to add a padding for the exporter
|
||||
width (+ width 8)]
|
||||
[:foreignObject {:x x
|
||||
:y y
|
||||
:id (:id shape)
|
||||
|
|
|
@ -35,11 +35,15 @@
|
|||
:exports exports}}))
|
||||
|
||||
(defn- trigger-download
|
||||
[name blob]
|
||||
[filename blob]
|
||||
(let [link (dom/create-element "a")
|
||||
uri (dom/create-uri blob)]
|
||||
uri (dom/create-uri blob)
|
||||
extension (dom/mtype->extension (.-type ^js blob))
|
||||
filename (if extension
|
||||
(str filename "." extension)
|
||||
filename)]
|
||||
(obj/set! link "href" uri)
|
||||
(obj/set! link "download" (str/slug name))
|
||||
(obj/set! link "download" filename)
|
||||
(obj/set! (.-style ^js link) "display" "none")
|
||||
(.appendChild (.-body ^js js/document) link)
|
||||
(.click link)
|
||||
|
@ -51,6 +55,11 @@
|
|||
exports (:exports shape [])
|
||||
loading? (mf/use-state false)
|
||||
|
||||
filename (cond-> (:name shape)
|
||||
(and (= (count exports) 1)
|
||||
(not (empty (:suffix (first exports)))))
|
||||
(str (:suffix (first exports))))
|
||||
|
||||
on-download
|
||||
(mf/use-callback
|
||||
(mf/deps shape)
|
||||
|
@ -62,7 +71,7 @@
|
|||
(fn [{:keys [status body] :as response}]
|
||||
(js/console.log status body)
|
||||
(if (= status 200)
|
||||
(trigger-download (:name shape) body)
|
||||
(trigger-download filename body)
|
||||
(st/emit! (dm/error (tr "errors.unexpected-error")))))
|
||||
(constantly nil)
|
||||
(fn []
|
||||
|
|
|
@ -257,3 +257,15 @@
|
|||
|
||||
(defn get-data [^js node ^string attr]
|
||||
(.getAttribute node (str "data-" attr)))
|
||||
|
||||
(defn mtype->extension [mtype]
|
||||
;; https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types
|
||||
(case mtype
|
||||
"image/apng" "apng"
|
||||
"image/avif" "avif"
|
||||
"image/gif" "gif"
|
||||
"image/jpeg" "jpg"
|
||||
"image/png" "png"
|
||||
"image/svg+xml" "svg"
|
||||
"image/webp" "webp"
|
||||
nil))
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
(def ^:private cancel-idle-callback #(js/cancelIdleCallback %)))
|
||||
(do
|
||||
(def ^:private request-idle-callback #(js/setTimeout % 100))
|
||||
(def ^:private cancel-idle-callback #(js/cancelTimeout %))))
|
||||
(def ^:private cancel-idle-callback #(js/clearTimeout %))))
|
||||
|
||||
(defn schedule-on-idle
|
||||
[func]
|
||||
|
|
Loading…
Add table
Reference in a new issue