mirror of
https://github.com/penpot/penpot.git
synced 2025-06-21 01:27:00 +02:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
c841ed6419
22 changed files with 173 additions and 160 deletions
10
CHANGES.md
10
CHANGES.md
|
@ -42,6 +42,7 @@
|
||||||
|
|
||||||
### :bug: Bugs fixed
|
### :bug: Bugs fixed
|
||||||
|
|
||||||
|
- Fix problem with constraints buttons [Taiga #8465](https://tree.taiga.io/project/penpot/issue/8465)
|
||||||
- Fix problem with go back button on error page [Taiga #8887](https://tree.taiga.io/project/penpot/issue/8887)
|
- Fix problem with go back button on error page [Taiga #8887](https://tree.taiga.io/project/penpot/issue/8887)
|
||||||
- Fix problem with shadows in text for Safari [Taiga #8770](https://tree.taiga.io/project/penpot/issue/8770)
|
- Fix problem with shadows in text for Safari [Taiga #8770](https://tree.taiga.io/project/penpot/issue/8770)
|
||||||
- Fix a regression with feedback form subject and content limits [Taiga #8908](https://tree.taiga.io/project/penpot/issue/8908)
|
- Fix a regression with feedback form subject and content limits [Taiga #8908](https://tree.taiga.io/project/penpot/issue/8908)
|
||||||
|
@ -50,6 +51,15 @@
|
||||||
- Fix problem with precision on boolean calculation [Taiga #8482](https://tree.taiga.io/project/penpot/issue/8482)
|
- Fix problem with precision on boolean calculation [Taiga #8482](https://tree.taiga.io/project/penpot/issue/8482)
|
||||||
- Fix problem when translating multiple path points [Github #4459](https://github.com/penpot/penpot/issues/4459)
|
- Fix problem when translating multiple path points [Github #4459](https://github.com/penpot/penpot/issues/4459)
|
||||||
- Fix problem on importing (and exporting) files with flows [Taiga #8914](https://tree.taiga.io/project/penpot/issue/8914)
|
- Fix problem on importing (and exporting) files with flows [Taiga #8914](https://tree.taiga.io/project/penpot/issue/8914)
|
||||||
|
- Fix Internal Error page: "go to your penpot" wrong design [Taiga #8922](https://tree.taiga.io/project/penpot/issue/8922)
|
||||||
|
- Fix problem updating layout when toggle visibility in component copy [Github #5143](https://github.com/penpot/penpot/issues/5143)
|
||||||
|
- Fix "Done" button on toolbar on inspect mode should go to design mode [Taiga #8933](https://tree.taiga.io/project/penpot/issue/8933)
|
||||||
|
- Fix problem with shortcuts in text editor [Github #5078](https://github.com/penpot/penpot/issues/5078)
|
||||||
|
- Fix problems with show in viewer and interactions [Github #4868](https://github.com/penpot/penpot/issues/4868)
|
||||||
|
- Add visual feedback when moving an element into a board [Github #3210](https://github.com/penpot/penpot/issues/3210)
|
||||||
|
- Fix percent calculation on grid layout tracks [Github #4688](https://github.com/penpot/penpot/issues/4688)
|
||||||
|
- Fix problem with caps and inner shadows [Github #4517](https://github.com/penpot/penpot/issues/4517)
|
||||||
|
- Fix problem with horizontal/vertical lines and shadows [Github #4516](https://github.com/penpot/penpot/issues/4516)
|
||||||
|
|
||||||
## 2.2.1
|
## 2.2.1
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,7 @@
|
||||||
|
|
||||||
(l/dbg :hint "run webhook"
|
(l/dbg :hint "run webhook"
|
||||||
:event-name (:name event)
|
:event-name (:name event)
|
||||||
:webhook-id (:id whook)
|
:webhook-id (str (:id whook))
|
||||||
:webhook-uri (:uri whook)
|
:webhook-uri (:uri whook)
|
||||||
:webhook-mtype (:mtype whook))
|
:webhook-mtype (:mtype whook))
|
||||||
|
|
||||||
|
|
|
@ -328,8 +328,10 @@
|
||||||
:page-name page-name
|
:page-name page-name
|
||||||
:position position
|
:position position
|
||||||
:content content
|
:content content
|
||||||
:frame-id frame-id}]
|
:frame-id frame-id}
|
||||||
(db/tx-run! cfg create-comment-thread params))))
|
thread (db/tx-run! cfg create-comment-thread params)]
|
||||||
|
|
||||||
|
(vary-meta thread assoc ::audit/props thread))))
|
||||||
|
|
||||||
(defn- create-comment-thread
|
(defn- create-comment-thread
|
||||||
[{:keys [::db/conn] :as cfg}
|
[{:keys [::db/conn] :as cfg}
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
filter-y (mth/min y (+ y offset-y (- spread) (- blur) -5))
|
filter-y (mth/min y (+ y offset-y (- spread) (- blur) -5))
|
||||||
filter-w (+ w (mth/abs offset-x) (* spread 2) (* blur 2) 10)
|
filter-w (+ w (mth/abs offset-x) (* spread 2) (* blur 2) 10)
|
||||||
filter-h (+ h (mth/abs offset-y) (* spread 2) (* blur 2) 10)]
|
filter-h (+ h (mth/abs offset-y) (* spread 2) (* blur 2) 10)]
|
||||||
|
|
||||||
(grc/make-rect filter-x filter-y filter-w filter-h)))
|
(grc/make-rect filter-x filter-y filter-w filter-h)))
|
||||||
|
|
||||||
(defn get-rect-filter-bounds
|
(defn get-rect-filter-bounds
|
||||||
|
@ -101,7 +102,7 @@
|
||||||
(map #(case (get % :stroke-alignment :center)
|
(map #(case (get % :stroke-alignment :center)
|
||||||
:center (/ (:stroke-width % 0) 2)
|
:center (/ (:stroke-width % 0) 2)
|
||||||
:outer (:stroke-width % 0)
|
:outer (:stroke-width % 0)
|
||||||
0))
|
(:stroke-width % 0)))
|
||||||
(reduce d/max 0))
|
(reduce d/max 0))
|
||||||
|
|
||||||
stroke-margin
|
stroke-margin
|
||||||
|
|
|
@ -124,7 +124,7 @@
|
||||||
;; All parents of any deleted shape must be resized.
|
;; All parents of any deleted shape must be resized.
|
||||||
(into res (cfh/get-parent-ids objects id)))
|
(into res (cfh/get-parent-ids objects id)))
|
||||||
(d/ordered-set)
|
(d/ordered-set)
|
||||||
ids-to-delete)
|
(concat ids-to-delete ids-to-hide))
|
||||||
|
|
||||||
all-children
|
all-children
|
||||||
(->> ids-to-delete ;; Children of deleted shapes must be also deleted.
|
(->> ids-to-delete ;; Children of deleted shapes must be also deleted.
|
||||||
|
@ -408,17 +408,12 @@
|
||||||
;; Resize parent containers that need to
|
;; Resize parent containers that need to
|
||||||
(pcb/resize-parents parents))))
|
(pcb/resize-parents parents))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn change-show-in-viewer [shape hide?]
|
(defn change-show-in-viewer [shape hide?]
|
||||||
(cond-> (assoc shape :hide-in-viewer hide?)
|
(assoc shape :hide-in-viewer hide?))
|
||||||
;; When a frame is no longer shown in view mode, it cannot have interactions
|
|
||||||
hide?
|
|
||||||
(dissoc :interactions)))
|
|
||||||
|
|
||||||
(defn add-new-interaction [shape interaction]
|
(defn add-new-interaction [shape interaction]
|
||||||
(-> shape
|
(-> shape
|
||||||
(update :interactions ctsi/add-interaction interaction)
|
(update :interactions ctsi/add-interaction interaction)))
|
||||||
;; When a interaction is created, the frame must be shown in view mode
|
|
||||||
(dissoc :hide-in-viewer)))
|
(defn show-in-viewer [shape]
|
||||||
|
(dissoc shape :hide-in-viewer))
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
;;
|
|
||||||
;; Copyright (c) KALEIDOS INC
|
|
||||||
|
|
||||||
(ns common-tests.logic.hide-in-viewer-test
|
|
||||||
(:require
|
|
||||||
[app.common.files.changes-builder :as pcb]
|
|
||||||
[app.common.logic.shapes :as cls]
|
|
||||||
[app.common.test-helpers.compositions :as tho]
|
|
||||||
[app.common.test-helpers.files :as thf]
|
|
||||||
[app.common.test-helpers.ids-map :as thi]
|
|
||||||
[app.common.test-helpers.shapes :as ths]
|
|
||||||
[app.common.types.shape.interactions :as ctsi]
|
|
||||||
[clojure.test :as t]))
|
|
||||||
|
|
||||||
(t/use-fixtures :each thi/test-fixture)
|
|
||||||
|
|
||||||
|
|
||||||
(t/deftest test-remove-show-in-view-mode-delete-interactions
|
|
||||||
(let [;; ==== Setup
|
|
||||||
|
|
||||||
file (-> (thf/sample-file :file1)
|
|
||||||
(tho/add-frame :frame-dest)
|
|
||||||
(tho/add-frame :frame-origin)
|
|
||||||
(ths/add-interaction :frame-origin :frame-dest))
|
|
||||||
|
|
||||||
frame-origin (ths/get-shape file :frame-origin)
|
|
||||||
|
|
||||||
page (thf/current-page file)
|
|
||||||
|
|
||||||
|
|
||||||
;; ==== Action
|
|
||||||
changes (-> (pcb/empty-changes nil (:id page))
|
|
||||||
(pcb/with-objects (:objects page))
|
|
||||||
(pcb/update-shapes [(:id frame-origin)] #(cls/change-show-in-viewer % true)))
|
|
||||||
file' (thf/apply-changes file changes)
|
|
||||||
|
|
||||||
;; ==== Get
|
|
||||||
frame-origin' (ths/get-shape file' :frame-origin)]
|
|
||||||
|
|
||||||
;; ==== Check
|
|
||||||
(t/is (some? (:interactions frame-origin)))
|
|
||||||
(t/is (nil? (:interactions frame-origin')))))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(t/deftest test-add-new-interaction-updates-show-in-view-mode
|
|
||||||
(let [;; ==== Setup
|
|
||||||
|
|
||||||
file (-> (thf/sample-file :file1)
|
|
||||||
(tho/add-frame :frame-dest :hide-in-viewer true)
|
|
||||||
(tho/add-frame :frame-origin :hide-in-viewer true))
|
|
||||||
frame-dest (ths/get-shape file :frame-dest)
|
|
||||||
frame-origin (ths/get-shape file :frame-origin)
|
|
||||||
|
|
||||||
page (thf/current-page file)
|
|
||||||
|
|
||||||
;; ==== Action
|
|
||||||
new-interaction (-> ctsi/default-interaction
|
|
||||||
(ctsi/set-destination (:id frame-dest))
|
|
||||||
(assoc :position-relative-to (:id frame-dest)))
|
|
||||||
|
|
||||||
changes (-> (pcb/empty-changes nil (:id page))
|
|
||||||
(pcb/with-objects (:objects page))
|
|
||||||
(pcb/update-shapes [(:id frame-origin)] #(cls/add-new-interaction % new-interaction)))
|
|
||||||
file' (thf/apply-changes file changes)
|
|
||||||
|
|
||||||
;; ==== Get
|
|
||||||
frame-origin' (ths/get-shape file' :frame-origin)]
|
|
||||||
|
|
||||||
;; ==== Check
|
|
||||||
(t/is (true? (:hide-in-viewer frame-origin)))
|
|
||||||
(t/is (nil? (:hide-in-viewer frame-origin')))))
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
export PATH=/usr/lib/jvm/openjdk/bin:/usr/local/nodejs/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
|
export PATH=/usr/lib/jvm/openjdk/bin:/usr/local/nodejs/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
|
||||||
export JAVA_OPTS="-Xmx1000m -Xms50m"
|
export JAVA_OPTS=${JAVA_OPTS:-"-Xmx1000m -Xms200m"};
|
||||||
|
|
||||||
alias l='ls --color -GFlh'
|
alias l='ls --color -GFlh'
|
||||||
alias rm='rm -r'
|
alias rm='rm -r'
|
||||||
|
|
|
@ -10,7 +10,7 @@ rm -rf target
|
||||||
export NODE_ENV=production;
|
export NODE_ENV=production;
|
||||||
|
|
||||||
# Build the application
|
# Build the application
|
||||||
clojure -J-Xms100M -J-Xmx1000M -J-XX:+UseSerialGC -M:dev:shadow-cljs release main;
|
clojure -M:dev:shadow-cljs release main;
|
||||||
|
|
||||||
# Remove source
|
# Remove source
|
||||||
rm -rf target/app;
|
rm -rf target/app;
|
||||||
|
|
|
@ -111,6 +111,7 @@
|
||||||
(def flex-help-uri (obj/get global "penpotGridHelpURI" "https://help.penpot.app/user-guide/flexible-layouts/"))
|
(def flex-help-uri (obj/get global "penpotGridHelpURI" "https://help.penpot.app/user-guide/flexible-layouts/"))
|
||||||
(def grid-help-uri (obj/get global "penpotGridHelpURI" "https://help.penpot.app/user-guide/flexible-layouts/"))
|
(def grid-help-uri (obj/get global "penpotGridHelpURI" "https://help.penpot.app/user-guide/flexible-layouts/"))
|
||||||
(def plugins-list-uri (obj/get global "penpotPluginsListUri" "https://penpot-docs-plugins.pages.dev/plugins/getting-started/#examples"))
|
(def plugins-list-uri (obj/get global "penpotPluginsListUri" "https://penpot-docs-plugins.pages.dev/plugins/getting-started/#examples"))
|
||||||
|
(def plugins-whitelist (into #{} (obj/get global "penpotPluginsWhitelist" [])))
|
||||||
|
|
||||||
(defn- normalize-uri
|
(defn- normalize-uri
|
||||||
[uri-str]
|
[uri-str]
|
||||||
|
|
|
@ -24,6 +24,10 @@ target.stopCallback = function (e, element, combo) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if ('composedPath' in e && typeof e.composedPath === 'function') {
|
if ('composedPath' in e && typeof e.composedPath === 'function') {
|
||||||
// For open shadow trees, update `element` so that the following check works.
|
// For open shadow trees, update `element` so that the following check works.
|
||||||
const initialEventTarget = e.composedPath()[0];
|
const initialEventTarget = e.composedPath()[0];
|
||||||
|
|
|
@ -147,11 +147,15 @@
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [page-id (or page-id (:current-page-id state))]
|
(let [page-id (or page-id (:current-page-id state))]
|
||||||
(rx/of (dwsh/update-shapes
|
(rx/of (dwsh/update-shapes [shape-id]
|
||||||
[shape-id]
|
|
||||||
(fn [shape]
|
(fn [shape]
|
||||||
(cls/add-new-interaction shape interaction))
|
(cls/add-new-interaction shape interaction))
|
||||||
{:page-id page-id}))))))
|
{:page-id page-id})
|
||||||
|
|
||||||
|
(when (:destination interaction)
|
||||||
|
(dwsh/update-shapes [(:destination interaction)]
|
||||||
|
cls/show-in-viewer
|
||||||
|
{:page-id page-id})))))))
|
||||||
|
|
||||||
(defn add-new-interaction
|
(defn add-new-interaction
|
||||||
([shape] (add-new-interaction shape nil))
|
([shape] (add-new-interaction shape nil))
|
||||||
|
@ -167,15 +171,20 @@
|
||||||
flows (get page :objects)
|
flows (get page :objects)
|
||||||
flow (ctp/get-frame-flow flows (:id frame))]
|
flow (ctp/get-frame-flow flows (:id frame))]
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(rx/of (dwsh/update-shapes [(:id shape)]
|
(rx/of (dwsh/update-shapes
|
||||||
|
[(:id shape)]
|
||||||
(fn [shape]
|
(fn [shape]
|
||||||
(let [new-interaction (-> ctsi/default-interaction
|
(let [new-interaction (-> ctsi/default-interaction
|
||||||
(ctsi/set-destination destination)
|
(ctsi/set-destination destination)
|
||||||
(assoc :position-relative-to (:id shape)))]
|
(assoc :position-relative-to (:id shape)))]
|
||||||
(cls/add-new-interaction shape new-interaction)))))
|
(cls/add-new-interaction shape new-interaction))))
|
||||||
|
|
||||||
|
(when destination
|
||||||
|
(dwsh/update-shapes [destination] cls/show-in-viewer))
|
||||||
|
|
||||||
(when (and (not (connected-frame? objects (:id frame)))
|
(when (and (not (connected-frame? objects (:id frame)))
|
||||||
(nil? flow))
|
(nil? flow))
|
||||||
(rx/of (add-flow (:id frame))))))))))
|
(add-flow (:id frame))))))))))
|
||||||
|
|
||||||
(defn remove-interaction
|
(defn remove-interaction
|
||||||
([shape index]
|
([shape index]
|
||||||
|
@ -186,8 +195,7 @@
|
||||||
(watch [_ _ _]
|
(watch [_ _ _]
|
||||||
(rx/of (dwsh/update-shapes [(:id shape)]
|
(rx/of (dwsh/update-shapes [(:id shape)]
|
||||||
(fn [shape]
|
(fn [shape]
|
||||||
(update shape :interactions
|
(update shape :interactions ctsi/remove-interaction index))
|
||||||
ctsi/remove-interaction index))
|
|
||||||
{:page-id page-id}))))))
|
{:page-id page-id}))))))
|
||||||
(defn update-interaction
|
(defn update-interaction
|
||||||
([shape index update-fn]
|
([shape index update-fn]
|
||||||
|
@ -196,11 +204,16 @@
|
||||||
(ptk/reify ::update-interaction
|
(ptk/reify ::update-interaction
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ _ _]
|
||||||
(rx/of (dwsh/update-shapes [(:id shape)]
|
(let [interactions (ctsi/update-interaction (:interactions shape) index update-fn)
|
||||||
|
interaction (nth interactions index)]
|
||||||
|
(rx/of (dwsh/update-shapes
|
||||||
|
[(:id shape)]
|
||||||
(fn [shape]
|
(fn [shape]
|
||||||
(update shape :interactions
|
(assoc shape :interactions interactions))
|
||||||
ctsi/update-interaction index update-fn))
|
options)
|
||||||
options))))))
|
|
||||||
|
(when (some? (:destination interaction))
|
||||||
|
(dwsh/update-shapes [(:destination interaction)] cls/show-in-viewer options))))))))
|
||||||
|
|
||||||
(defn remove-all-interactions-nav-to
|
(defn remove-all-interactions-nav-to
|
||||||
"Remove all interactions that navigate to the given frame."
|
"Remove all interactions that navigate to the given frame."
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.geom.shapes.bounds :as gsb]
|
[app.common.geom.shapes.bounds :as gsb]
|
||||||
|
[app.common.math :as mth]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
@ -129,6 +130,34 @@
|
||||||
[filters]
|
[filters]
|
||||||
(map #(assoc %1 :filter-in %2) filters (cons nil (map :id filters))))
|
(map #(assoc %1 :filter-in %2) filters (cons nil (map :id filters))))
|
||||||
|
|
||||||
|
(defn filter-coords
|
||||||
|
[bounds selrect padding]
|
||||||
|
(if (or (mth/close? 0.01 (:width selrect))
|
||||||
|
(mth/close? 0.01 (:height selrect)))
|
||||||
|
|
||||||
|
;; We cannot use "objectBoundingbox" if the shape doesn't have width/heigth
|
||||||
|
;; From the SVG spec (https://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
|
||||||
|
;; Keyword objectBoundingBox should not be used when the geometry of the applicable element
|
||||||
|
;; has no width or no height, such as the case of a horizontal or vertical line, even when
|
||||||
|
;; the line has actual thickness when viewed due to having a non-zero stroke width since
|
||||||
|
;; stroke width is ignored for bounding box calculations. When the geometry of the
|
||||||
|
;; applicable element has no width or height and objectBoundingBox is specified, then
|
||||||
|
;; the given effect (e.g., a gradient or a filter) will be ignored.
|
||||||
|
(let [filter-width (+ (:width bounds) (* 2 (:horizontal padding)))
|
||||||
|
filter-height (+ (:height bounds) (* 2 (:vertical padding)))
|
||||||
|
filter-x (- (:x bounds) #_(:x selrect) (:horizontal padding))
|
||||||
|
filter-y (- (:y bounds) #_(:y selrect) (:vertical padding))
|
||||||
|
filter-units "userSpaceOnUse"]
|
||||||
|
[filter-x filter-y filter-width filter-height filter-units])
|
||||||
|
|
||||||
|
;; If the width/height is not zero we use objectBoundingBox as it's more stable
|
||||||
|
(let [filter-width (/ (+ (:width bounds) (* 2 (:horizontal padding))) (:width selrect))
|
||||||
|
filter-height (/ (+ (:height bounds) (* 2 (:vertical padding))) (:height selrect))
|
||||||
|
filter-x (/ (- (:x bounds) (:x selrect) (:horizontal padding)) (:width selrect))
|
||||||
|
filter-y (/ (- (:y bounds) (:y selrect) (:vertical padding)) (:height selrect))
|
||||||
|
filter-units "objectBoundingBox"]
|
||||||
|
[filter-x filter-y filter-width filter-height filter-units])))
|
||||||
|
|
||||||
(mf/defc filters
|
(mf/defc filters
|
||||||
[{:keys [filter-id shape]}]
|
[{:keys [filter-id shape]}]
|
||||||
|
|
||||||
|
@ -136,17 +165,17 @@
|
||||||
bounds (gsb/get-rect-filter-bounds (:selrect shape) filters (or (-> shape :blur :value) 0))
|
bounds (gsb/get-rect-filter-bounds (:selrect shape) filters (or (-> shape :blur :value) 0))
|
||||||
padding (gsb/calculate-padding shape)
|
padding (gsb/calculate-padding shape)
|
||||||
selrect (:selrect shape)
|
selrect (:selrect shape)
|
||||||
filter-x (/ (- (:x bounds) (:x selrect) (:horizontal padding)) (:width selrect))
|
|
||||||
filter-y (/ (- (:y bounds) (:y selrect) (:vertical padding)) (:height selrect))
|
[filter-x filter-y filter-width filter-height filter-units]
|
||||||
filter-width (/ (+ (:width bounds) (* 2 (:horizontal padding))) (:width selrect))
|
(filter-coords bounds selrect padding)]
|
||||||
filter-height (/ (+ (:height bounds) (* 2 (:vertical padding))) (:height selrect))]
|
|
||||||
(when (> (count filters) 2)
|
(when (> (count filters) 2)
|
||||||
[:filter {:id filter-id
|
[:filter {:id filter-id
|
||||||
:x filter-x
|
:x filter-x
|
||||||
:y filter-y
|
:y filter-y
|
||||||
:width filter-width
|
:width filter-width
|
||||||
:height filter-height
|
:height filter-height
|
||||||
:filterUnits "objectBoundingBox"
|
:filterUnits filter-units
|
||||||
:color-interpolation-filters "sRGB"}
|
:color-interpolation-filters "sRGB"}
|
||||||
(for [[index entry] (d/enumerate filters)]
|
(for [[index entry] (d/enumerate filters)]
|
||||||
[:& filter-entry {:key (dm/str filter-id "-" index)
|
[:& filter-entry {:key (dm/str filter-id "-" index)
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
[app.main.ui.auth.recovery-request :refer [recovery-request-page recovery-sent-page]]
|
[app.main.ui.auth.recovery-request :refer [recovery-request-page recovery-sent-page]]
|
||||||
[app.main.ui.auth.register :as register]
|
[app.main.ui.auth.register :as register]
|
||||||
[app.main.ui.dashboard.sidebar :refer [sidebar]]
|
[app.main.ui.dashboard.sidebar :refer [sidebar]]
|
||||||
|
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
|
||||||
|
[app.main.ui.ds.foundations.assets.raw-svg :refer [raw-svg*]]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.main.ui.viewer.header :as viewer.header]
|
[app.main.ui.viewer.header :as viewer.header]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
|
@ -43,9 +45,9 @@
|
||||||
[:button
|
[:button
|
||||||
{:class (stl/css :exception-header)
|
{:class (stl/css :exception-header)
|
||||||
:on-click on-nav-root}
|
:on-click on-nav-root}
|
||||||
i/logo-icon
|
[:> raw-svg* {:id "penpot-logo-icon" :class (stl/css :penpot-logo)}]
|
||||||
(when profile-id
|
(when profile-id
|
||||||
(str "< " (tr "not-found.no-permission.go-dashboard")))]
|
[:div {:class (stl/css :go-back-wrapper)} [:> icon* {:id "arrow" :class (stl/css :back-arrow)}] [:span (tr "not-found.no-permission.go-dashboard")]])]
|
||||||
[:div {:class (stl/css :deco-before)} i/logo-error-screen]
|
[:div {:class (stl/css :deco-before)} i/logo-error-screen]
|
||||||
(when-not profile-id
|
(when-not profile-id
|
||||||
[:button {:class (stl/css :login-header)
|
[:button {:class (stl/css :login-header)
|
||||||
|
|
|
@ -66,6 +66,7 @@
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 25%;
|
width: 25%;
|
||||||
|
padding-bottom: $s-28;
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
@ -82,12 +83,25 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
svg {
|
.penpot-logo {
|
||||||
fill: var(--color-foreground-primary);
|
fill: var(--color-foreground-primary);
|
||||||
width: $s-48;
|
width: $s-48;
|
||||||
height: auto;
|
height: $s-48;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.back-arrow {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.go-back-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: $s-8;
|
||||||
|
margin-left: $s-12;
|
||||||
|
font-size: $fs-14;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-header {
|
.login-header {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.config :as cf]
|
[app.config :as cfg]
|
||||||
[app.main.data.events :as ev]
|
[app.main.data.events :as ev]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.plugins :as dp]
|
[app.main.data.plugins :as dp]
|
||||||
|
@ -169,7 +169,7 @@
|
||||||
[:> i18n/tr-html*
|
[:> i18n/tr-html*
|
||||||
{:class (stl/css :discover)
|
{:class (stl/css :discover)
|
||||||
:on-click #(st/emit! (ptk/event ::ev/event {::ev/name "open-plugins-list"}))
|
:on-click #(st/emit! (ptk/event ::ev/event {::ev/name "open-plugins-list"}))
|
||||||
:content (tr "workspace.plugins.discover" cf/plugins-list-uri)}])
|
:content (tr "workspace.plugins.discover" cfg/plugins-list-uri)}])
|
||||||
|
|
||||||
[:hr]
|
[:hr]
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@
|
||||||
[:div {:class (stl/css :plugins-empty-logo)} i/puzzle]
|
[:div {:class (stl/css :plugins-empty-logo)} i/puzzle]
|
||||||
[:div {:class (stl/css :plugins-empty-text)} (tr "workspace.plugins.empty-plugins")]
|
[:div {:class (stl/css :plugins-empty-text)} (tr "workspace.plugins.empty-plugins")]
|
||||||
[:a {:class (stl/css :plugins-link)
|
[:a {:class (stl/css :plugins-link)
|
||||||
:href cf/plugins-list-uri
|
:href cfg/plugins-list-uri
|
||||||
:target "_blank"
|
:target "_blank"
|
||||||
:on-click #(st/emit! (ptk/event ::ev/event {::ev/name "open-plugins-list"}))}
|
:on-click #(st/emit! (ptk/event ::ev/event {::ev/name "open-plugins-list"}))}
|
||||||
(tr "workspace.plugins.plugin-list-link") i/external-link]]
|
(tr "workspace.plugins.plugin-list-link") i/external-link]]
|
||||||
|
@ -287,8 +287,9 @@
|
||||||
[:div {:class (stl/css :modal-content)}
|
[:div {:class (stl/css :modal-content)}
|
||||||
[:& plugins-permission-list {:permissions permissions}]
|
[:& plugins-permission-list {:permissions permissions}]
|
||||||
|
|
||||||
|
(when-not (contains? cfg/plugins-whitelist host)
|
||||||
[:div {:class (stl/css :permissions-disclaimer)}
|
[:div {:class (stl/css :permissions-disclaimer)}
|
||||||
(tr "workspace.plugins.permissions.disclaimer")]]
|
(tr "workspace.plugins.permissions.disclaimer")])]
|
||||||
|
|
||||||
[:div {:class (stl/css :modal-footer)}
|
[:div {:class (stl/css :modal-footer)}
|
||||||
[:div {:class (stl/css :action-buttons)}
|
[:div {:class (stl/css :action-buttons)}
|
||||||
|
|
|
@ -272,7 +272,7 @@ div.input-error {
|
||||||
@include bodySmallTypography;
|
@include bodySmallTypography;
|
||||||
padding: $s-16;
|
padding: $s-16;
|
||||||
background: var(--color-background-quaternary);
|
background: var(--color-background-quaternary);
|
||||||
color: var(--color-foreground-quaternary);
|
color: var(--color-foreground-primary);
|
||||||
border-radius: $br-4;
|
border-radius: $br-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,6 +138,8 @@
|
||||||
first-selected-shape (first selected-shapes)
|
first-selected-shape (first selected-shapes)
|
||||||
shape-parent-frame (cfh/get-frame objects (:frame-id first-selected-shape))
|
shape-parent-frame (cfh/get-frame objects (:frame-id first-selected-shape))
|
||||||
|
|
||||||
|
options-mode (mf/deref refs/options-mode-global)
|
||||||
|
|
||||||
on-change-tab
|
on-change-tab
|
||||||
(fn [options-mode]
|
(fn [options-mode]
|
||||||
(let [options-mode (keyword options-mode)]
|
(let [options-mode (keyword options-mode)]
|
||||||
|
@ -187,6 +189,7 @@
|
||||||
[:> tab-switcher* {:tabs tabs
|
[:> tab-switcher* {:tabs tabs
|
||||||
:default-selected "info"
|
:default-selected "info"
|
||||||
:on-change-tab on-change-tab
|
:on-change-tab on-change-tab
|
||||||
|
:selected (name options-mode)
|
||||||
:class (stl/css :options-tab-switcher)}]]))
|
:class (stl/css :options-tab-switcher)}]]))
|
||||||
|
|
||||||
;; TODO: this need optimizations, selected-objects and
|
;; TODO: this need optimizations, selected-objects and
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
.constraints-bottom {
|
.constraints-bottom {
|
||||||
@include flexCenter;
|
@include flexCenter;
|
||||||
grid-area: top;
|
grid-area: top;
|
||||||
|
}
|
||||||
.constraint-btn,
|
.constraint-btn,
|
||||||
.constraint-btn-special,
|
.constraint-btn-special,
|
||||||
.constraint-btn-rotated {
|
.constraint-btn-rotated {
|
||||||
|
@ -43,25 +44,29 @@
|
||||||
@include flexCenter;
|
@include flexCenter;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
--resalted-area-background-color: var(--button-constraint-background-color-rest);
|
||||||
|
--resalted-area-border-color: none;
|
||||||
|
&.active {
|
||||||
|
--resalted-area-border-color: var(--button-constraint-border-color-hover);
|
||||||
|
--resalted-area-background-color: var(--button-constraint-background-color-hover);
|
||||||
|
}
|
||||||
|
&:hover,
|
||||||
|
&:focus-visible {
|
||||||
|
--resalted-area-border-color: var(--button-constraint-border-color-hover);
|
||||||
|
--resalted-area-background-color: var(--button-constraint-background-color-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.resalted-area {
|
.resalted-area {
|
||||||
width: $s-32;
|
width: $s-32;
|
||||||
height: $s-3;
|
height: $s-3;
|
||||||
border-radius: $br-8;
|
border-radius: $br-8;
|
||||||
background-color: var(--button-constraint-background-color-rest);
|
background-color: var(--resalted-area-background-color);
|
||||||
|
outline: $s-4 solid var(--resalted-area-border-color);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
&.active .resalted-area {
|
|
||||||
outline: $s-4 solid var(--button-constraint-border-color-hover);
|
|
||||||
background-color: var(--button-constraint-background-color-hover);
|
|
||||||
}
|
|
||||||
&:hover .resalted-area,
|
|
||||||
&:focus .resalted-area {
|
|
||||||
outline: $s-4 solid var(--button-constraint-border-color-hover);
|
|
||||||
background-color: var(--button-constraint-background-color-hover);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.constraints-left {
|
.constraints-left {
|
||||||
grid-area: left;
|
grid-area: left;
|
||||||
.constraint-btn-rotated {
|
.constraint-btn-rotated {
|
||||||
|
@ -73,6 +78,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.constraints-center {
|
.constraints-center {
|
||||||
grid-area: center;
|
grid-area: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -113,7 +119,7 @@
|
||||||
grid-area: bottom;
|
grid-area: bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contraints-selects {
|
.constraints-selects {
|
||||||
@include flexColumn;
|
@include flexColumn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -677,7 +677,7 @@
|
||||||
[{:keys [type value]}]
|
[{:keys [type value]}]
|
||||||
(case type
|
(case type
|
||||||
:auto "auto"
|
:auto "auto"
|
||||||
:percent (fmt/format-percent value)
|
:percent (fmt/format-percent (/ value 100))
|
||||||
:flex (fmt/format-frs value)
|
:flex (fmt/format-frs value)
|
||||||
:fixed (fmt/format-pixels value)
|
:fixed (fmt/format-pixels value)
|
||||||
value))
|
value))
|
||||||
|
|
|
@ -150,6 +150,7 @@
|
||||||
.grid-layout-menu {
|
.grid-layout-menu {
|
||||||
@include flexColumn;
|
@include flexColumn;
|
||||||
gap: $s-8;
|
gap: $s-8;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.row {
|
.row {
|
||||||
@include flexRow;
|
@include flexRow;
|
||||||
|
|
|
@ -397,7 +397,7 @@
|
||||||
(->> @hover-ids
|
(->> @hover-ids
|
||||||
(filter #(cfh/frame-shape? (get base-objects %)))
|
(filter #(cfh/frame-shape? (get base-objects %)))
|
||||||
(remove selected)
|
(remove selected)
|
||||||
(first))
|
(last))
|
||||||
outlined-frame (get objects outlined-frame-id)]
|
outlined-frame (get objects outlined-frame-id)]
|
||||||
[:*
|
[:*
|
||||||
[:& outline/shape-outlines
|
[:& outline/shape-outlines
|
||||||
|
|
10
manage.sh
10
manage.sh
|
@ -7,6 +7,9 @@ export DEVENV_PNAME="penpotdev";
|
||||||
export CURRENT_USER_ID=$(id -u);
|
export CURRENT_USER_ID=$(id -u);
|
||||||
export CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD);
|
export CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD);
|
||||||
|
|
||||||
|
# Set default java options
|
||||||
|
export JAVA_OPTS=${JAVA_OPTS:-"-Xmx1000m -Xms50m"};
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
function print-current-version {
|
function print-current-version {
|
||||||
|
@ -95,10 +98,12 @@ function run-devenv-shell {
|
||||||
if [[ ! $(docker ps -f "name=penpot-devenv-main" -q) ]]; then
|
if [[ ! $(docker ps -f "name=penpot-devenv-main" -q) ]]; then
|
||||||
start-devenv
|
start-devenv
|
||||||
fi
|
fi
|
||||||
docker exec -ti penpot-devenv-main sudo -EH -u penpot bash
|
docker exec -ti \
|
||||||
|
-e JAVA_OPTS="$JAVA_OPTS" \
|
||||||
|
-e EXTERNAL_UID=$CURRENT_USER_ID \
|
||||||
|
penpot-devenv-main sudo -EH -u penpot bash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function build {
|
function build {
|
||||||
echo ">> build start: $1"
|
echo ">> build start: $1"
|
||||||
local version=$(print-current-version);
|
local version=$(print-current-version);
|
||||||
|
@ -111,6 +116,7 @@ function build {
|
||||||
-e EXTERNAL_UID=$CURRENT_USER_ID \
|
-e EXTERNAL_UID=$CURRENT_USER_ID \
|
||||||
-e BUILD_STORYBOOK=$BUILD_STORYBOOK \
|
-e BUILD_STORYBOOK=$BUILD_STORYBOOK \
|
||||||
-e SHADOWCLJS_EXTRA_PARAMS=$SHADOWCLJS_EXTRA_PARAMS \
|
-e SHADOWCLJS_EXTRA_PARAMS=$SHADOWCLJS_EXTRA_PARAMS \
|
||||||
|
-e JAVA_OPTS="$JAVA_OPTS" \
|
||||||
-w /home/penpot/penpot/$1 \
|
-w /home/penpot/penpot/$1 \
|
||||||
$DEVENV_IMGNAME:latest sudo -EH -u penpot ./scripts/build $version
|
$DEVENV_IMGNAME:latest sudo -EH -u penpot ./scripts/build $version
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue