Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
Andrey Antukh 2024-01-30 15:34:50 +01:00
commit cb6e3a2e3c
33 changed files with 419 additions and 81 deletions

View File

@ -728,10 +728,11 @@
(defmethod read-section :v1/files
[{:keys [::db/conn ::input ::project-id ::enabled-features ::timestamp ::overwrite?] :as system}]
[{:keys [::db/conn ::input ::project-id ::enabled-features ::timestamp ::overwrite? ::name] :as system}]
(doseq [expected-file-id (-> *state* deref :files)]
(doseq [[idx expected-file-id] (d/enumerate (-> *state* deref :files))]
(let [file (read-obj! input)
media (read-obj! input)
file-id (:id file)
@ -770,6 +771,8 @@
(let [file (-> file
(assoc :id file-id')
(cond-> (and (= idx 0) (some? name))
(assoc :name name))
(process-file))
;; All features that are enabled and requires explicit migration are
@ -1105,6 +1108,7 @@
schema:import-binfile
(sm/define
[:map {:title "import-binfile"}
[:name :string]
[:project-id ::sm/uuid]
[:file ::media/upload]]))
@ -1116,12 +1120,13 @@
::webhooks/event? true
::sse/stream? true
::sm/params schema:import-binfile}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id project-id file] :as params}]
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id name project-id file] :as params}]
(projects/check-read-permissions! pool profile-id project-id)
(let [params (-> cfg
(assoc ::input (:path file))
(assoc ::project-id project-id)
(assoc ::profile-id profile-id)
(assoc ::name name)
(assoc ::ignore-index-errors? true))]
(with-meta
(sse/response #(import-binfile params))

View File

@ -210,7 +210,8 @@
[:restore-component
[:map {:title "RestoreComponentChange"}
[:type [:= :restore-component]]
[:id ::sm/uuid]]]
[:id ::sm/uuid]
[:page-id ::sm/uuid]]]
[:purge-component
[:map {:title "PurgeComponentChange"}

View File

@ -742,13 +742,14 @@
changes)))
(defn delete-component
[changes id]
[changes id page-id]
(assert-library! changes)
(-> changes
(update :redo-changes conj {:type :del-component
:id id})
(update :undo-changes conj {:type :restore-component
:id id})))
:id id
:page-id page-id})))
(defn restore-component
([changes id]

View File

@ -44,6 +44,17 @@
(mth/to-fixed (.-e this) precision)
(mth/to-fixed (.-f this) precision))))
(defn format-precision
[mtx precision]
(when mtx
(dm/fmt "matrix(%, %, %, %, %, %)"
(mth/to-fixed (.-a mtx) precision)
(mth/to-fixed (.-b mtx) precision)
(mth/to-fixed (.-c mtx) precision)
(mth/to-fixed (.-d mtx) precision)
(mth/to-fixed (.-e mtx) precision)
(mth/to-fixed (.-f mtx) precision))))
(defn matrix?
"Return true if `v` is Matrix instance."
[v]

View File

@ -13,6 +13,7 @@
[app.common.files.helpers :as cfh]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.common.geom.shapes.tree-seq :as gsts]
[app.common.logging :as l]
[app.common.schema :as sm]
[app.common.text :as ct]
@ -176,6 +177,13 @@
(when (:shape-ref shape)
(get-component-shape file-data component (:shape-ref shape))))
(defn get-shape-in-copy
"Given a shape in the main component and the root of the copy component returns the equivalent
shape inside the root copy that matches the main-shape"
[file-data main-shape root-copy]
(->> (gsts/get-children-seq (:id root-copy) (:objects file-data))
(d/seek #(= (:shape-ref %) (:id main-shape)))))
(defn find-ref-shape
"Locate the near component in the local file or libraries, and retrieve the shape
referenced by the instance shape."
@ -351,10 +359,10 @@
(mapcat used-assets-container (containers-seq file-data))))
(defn get-or-add-library-page
"If exists a page named 'Library backup', get the id and calculate the position to start
"If exists a page named 'Main components', get the id and calculate the position to start
adding new components. If not, create it and start at (0, 0)."
[file-data grid-gap]
(let [library-page (d/seek #(= (:name %) "Library backup") (ctpl/pages-seq file-data))]
(let [library-page (d/seek #(= (:name %) "Main components") (ctpl/pages-seq file-data))]
(if (some? library-page)
(let [compare-pos (fn [pos shape]
(let [bounds (gsh/bounding-box shape)]
@ -366,7 +374,7 @@
(gpt/point 0 0)
(ctn/shapes-seq library-page))]
[file-data (:id library-page) position])
(let [library-page (ctp/make-empty-page (uuid/next) "Library backup")]
(let [library-page (ctp/make-empty-page (uuid/next) "Main components")]
[(ctpl/add-page file-data library-page) (:id library-page) (gpt/point 0 0)]))))
(defn- absorb-components

View File

@ -102,7 +102,7 @@
(t/is (= (count pages) 2))
(t/is (= (:name (first pages)) "Page 1"))
(t/is (= (:name (second pages)) "Library backup"))
(t/is (= (:name (second pages)) "Main components"))
(t/is (= (count components) 1))

View File

@ -10,6 +10,5 @@
// debugging.
body {
background-color: red;
color: yellow;
}

View File

@ -22,7 +22,7 @@
;; --- Auxiliar Functions
(def valid-browsers
#{:chrome :firefox :safari :edge :other})
#{:chrome :firefox :safari :safari-16 :safari-17 :edge :other})
(def valid-platforms
#{:windows :linux :macos :other})
@ -33,13 +33,17 @@
check-chrome? (fn [] (str/includes? user-agent "chrom"))
check-firefox? (fn [] (str/includes? user-agent "firefox"))
check-edge? (fn [] (str/includes? user-agent "edg"))
check-safari? (fn [] (str/includes? user-agent "safari"))]
check-safari? (fn [] (str/includes? user-agent "safari"))
check-safari-16? (fn [] (and (check-safari?) (str/includes? user-agent "version/16")))
check-safari-17? (fn [] (and (check-safari?) (str/includes? user-agent "version/17")))]
(cond
(check-edge?) :edge
(check-chrome?) :chrome
(check-firefox?) :firefox
(check-safari?) :safari
:else :other)))
(check-edge?) :edge
(check-chrome?) :chrome
(check-firefox?) :firefox
(check-safari-16?) :safari-16
(check-safari-17?) :safari-17
(check-safari?) :safari
:else :other)))
(defn- parse-platform
[]
@ -130,7 +134,9 @@
(defn ^boolean check-browser? [candidate]
(dm/assert! (contains? valid-browsers candidate))
(= candidate browser))
(if (= candidate :safari)
(contains? #{:safari :safari-16 :safari-17} browser)
(= candidate browser)))
(defn ^boolean check-platform? [candidate]
(dm/assert! (contains? valid-platforms candidate))

View File

@ -551,7 +551,7 @@
(map :component-id))
changes (reduce (fn [changes component-id]
(pcb/delete-component changes component-id))
(pcb/delete-component changes component-id (:id page)))
changes
components-to-delete)]
changes))

View File

@ -129,6 +129,9 @@
(->> ms/mouse-position
(rx/filter #(> (gpt/distance % initial) (/ 2 zoom)))
;; Take until before the snap calculation otherwise we could cancel the snap in the worker
;; and its a problem for fast moving drawing
(rx/take-until stoper)
(rx/with-latest-from ms/mouse-position-shift ms/mouse-position-mod)
(rx/switch-map
(fn [[point :as current]]
@ -136,8 +139,7 @@
(rx/map (partial array/conj current)))))
(rx/map
(fn [[_ shift? mod? point]]
#(update-drawing % initial (cond-> point snap-pixel? (gpt/round-step snap-prec)) shift? mod?)))))
(rx/take-until stoper))
#(update-drawing % initial (cond-> point snap-pixel? (gpt/round-step snap-prec)) shift? mod?))))))
(->> (rx/of (common/handle-finish-drawing))
(rx/delay 100)))))))

View File

@ -483,9 +483,10 @@
(rx/of
(dwt/clear-thumbnail (:current-file-id state) page-id root-id "component")
(dwsh/delete-shapes page-id #{root-id}))) ;; Deleting main root triggers component delete
(let [changes (-> (pcb/empty-changes it)
(let [page-id (:current-page-id state)
changes (-> (pcb/empty-changes it)
(pcb/with-library-data data)
(pcb/delete-component id))]
(pcb/delete-component id page-id))]
(rx/of (dch/commit-changes changes))))))))

View File

@ -51,6 +51,8 @@
(declare change-touched)
(declare change-remote-synced)
(declare update-attrs)
(declare update-grid-main-attrs)
(declare update-grid-copy-attrs)
(declare reposition-shape)
(declare make-change)
@ -665,6 +667,13 @@
container
omit-touched?)
(ctl/grid-layout? shape-main)
(update-grid-copy-attrs shape-main
shape-inst
library
component
container)
reset?
(change-touched shape-inst
shape-main
@ -836,6 +845,12 @@
component-container
{:copy-touched? true}))
(ctl/grid-layout? shape-main)
(update-grid-main-attrs shape-main
shape-inst
component-container
container)
clear-remote-synced?
(change-remote-synced shape-inst container nil)
@ -957,12 +972,12 @@
(recur (next children-inst)
(remove #(= (:id %) (:id child-main')) children-main)
(-> changes
(both-cb child-inst' child-main)
(both-cb child-inst child-main')
(moved-cb child-inst child-main')))
(recur (remove #(= (:id %) (:id child-inst')) children-inst)
(next children-main)
(-> changes
(both-cb child-inst child-main')
(both-cb child-inst' child-main)
(moved-cb child-inst' child-main)))))))))))
(defn- add-shape-to-instance
@ -1286,7 +1301,9 @@
origin-shape (reposition-shape origin-shape origin-root dest-root)
touched (get dest-shape :touched #{})]
(loop [attrs (seq (keys ctk/sync-attrs))
(loop [attrs (->> (seq (keys ctk/sync-attrs))
;; We don't do automatic update of the `layout-grid-cells` property.
(remove #(= :layout-grid-cells %)))
roperations []
uoperations '()]
@ -1335,6 +1352,50 @@
(conj roperations roperation)
(conj uoperations uoperation)))))))))
(defn- update-grid-copy-attrs
"Synchronizes the `layout-grid-cells` property from the main shape to the copies"
[changes shape-main shape-copy main-container main-component copy-container]
(let [ids-map
(into {}
(comp
(map #(dm/get-in copy-container [:objects %]))
(keep
(fn [copy-shape]
(let [main-shape (ctf/get-ref-shape main-container main-component copy-shape)]
[(:id main-shape) (:id copy-shape)]))))
(:shapes shape-copy))]
(-> changes
(pcb/with-container copy-container)
(pcb/update-shapes
[(:id shape-copy)]
(fn [shape-copy]
;; Take cells from main and remap the shapes to assign it to the copy
(let [new-cells (-> (ctl/remap-grid-cells shape-main ids-map) :layout-grid-cells)]
(assoc shape-copy :layout-grid-cells new-cells)))))))
(defn- update-grid-main-attrs
"Synchronizes the `layout-grid-cells` property from the copy to the main shape"
[changes shape-main shape-copy main-container copy-container]
(let [ids-map
(into {}
(comp
(map #(dm/get-in main-container [:objects %]))
(keep
(fn [main-shape]
(let [copy-shape (ctf/get-shape-in-copy copy-container main-shape shape-copy)]
[(:id copy-shape) (:id main-shape)]))))
(:shapes shape-main))]
(-> changes
(pcb/with-page main-container)
(pcb/with-objects (:objects main-container))
(pcb/update-shapes
[(:id shape-main)]
(fn [shape-main]
;; Take cells from copy and remap the shapes to assign it to the copy
(let [new-cells (-> (ctl/remap-grid-cells shape-copy ids-map) :layout-grid-cells)]
(assoc shape-main :layout-grid-cells new-cells)))))))
(defn- reposition-shape
[shape origin-root dest-root]
(let [shape-pos (fn [shape]

View File

@ -6,6 +6,7 @@
(ns app.main.data.workspace.media
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.exceptions :as ex]
[app.common.files.builder :as fb]
@ -308,9 +309,37 @@
process-svg
(fn [svg-data]
(let [[shape children]
(csvg.shapes-builder/create-svg-shapes svg-data pos objects uuid/zero nil #{} false)]
[shape children]))]
(let [[root-svg-shape children]
(csvg.shapes-builder/create-svg-shapes svg-data pos objects uuid/zero nil #{} false)
frame-shape
(cts/setup-shape
{:type :frame
:x (:x pos)
:y (:y pos)
:width (-> root-svg-shape :selrect :width)
:height (-> root-svg-shape :selrect :height)
:name (:name root-svg-shape)
:frame-id uuid/zero
:parent-id uuid/zero
:fills []})
root-svg-shape
(-> root-svg-shape
(assoc :frame-id (:id frame-shape) :parent-id (:id frame-shape)))
shapes
(->> children
(filter #(= (:parent-id %) (:id root-svg-shape)))
(mapv :id))
root-svg-shape
(assoc root-svg-shape :shapes shapes)
children (->> children (mapv #(assoc % :frame-id (:id frame-shape))))
children (d/concat-vec [root-svg-shape] children)]
[frame-shape children]))]
(->> (upload-images svg-data)
(rx/map process-svg))))
@ -427,4 +456,3 @@
(rx/tap on-success)
(rx/catch on-error)
(rx/finalize #(st/emit! (msg/hide-tag :media-loading)))))))))

View File

@ -240,7 +240,7 @@
changes (reduce (fn [changes component-id]
;; It's important to delete the component before the main instance, because we
;; need to store the instance position if we want to restore it later.
(pcb/delete-component changes component-id))
(pcb/delete-component changes component-id (:id page)))
changes
components-to-delete)

View File

@ -305,7 +305,7 @@
[:div {:class (stl/css :project-actions)}
(when-not (:is-default project)
[:> pin-button* {:is-pinned (:is-pinned project) :on-click toggle-pin :tab-index 0}])
[:> pin-button* {:class (stl/css :pin-button) :is-pinned (:is-pinned project) :on-click toggle-pin :tab-index 0}])
[:button
{:class (stl/css :btn-secondary :btn-small :tooltip :tooltip-bottom)

View File

@ -108,10 +108,7 @@
opacity: 1;
margin-left: $s-32;
svg {
fill: $df-primary;
}
.btn-small {
.btn-small:not(.pin-button) {
height: $s-32;
margin: 0 $s-8;
width: $s-32;
@ -120,6 +117,7 @@
background: transparent;
}
svg {
fill: $df-primary;
height: $s-16;
width: $s-16;
}

View File

@ -18,19 +18,19 @@
(mf/fnc bool-shape
{::mf/wrap-props false}
[props]
(let [shape (unchecked-get props "shape")
children (unchecked-get props "childs")
children (h/use-equal-memo children)
(let [shape (unchecked-get props "shape")
child-objs (unchecked-get props "childs")
child-objs (h/use-equal-memo child-objs)
metadata? (mf/use-ctx use/include-metadata-ctx)
content (mf/with-memo [shape children]
content (mf/with-memo [shape child-objs]
(let [content (:bool-content shape)]
(cond
(some? content)
content
(some? children)
(gsh/calc-bool-content shape children))))
(some? child-objs)
(gsh/calc-bool-content shape child-objs))))
shape (mf/with-memo [shape content]
(assoc shape :content content))]
@ -40,9 +40,8 @@
[:& path-shape {:shape shape}])
(when metadata?
;; FIXME: get children looks wrong
[:> "penpot:bool" {}
(for [item (map #(get children %) (:shapes shape))]
(for [item (map #(get child-objs %) (:shapes shape))]
[:& shape-wrapper
{:shape item
:key (dm/str (dm/get-prop item :id))}])])])))

View File

@ -58,7 +58,7 @@
:width width
:height height}
pat-props (if (= :path type)
pat-props (if (or (= :path type) (= :bool type))
(obj/set! pat-props "patternTransform" transform)
pat-props)]

View File

@ -179,7 +179,7 @@
:on-key-down (fn [event]
(when (kbd/enter? event)
(toggle-flag event)))
:data-test "scale.-text"
:data-test "scale-text"
:id "file-menu-scale-text"}
[:span {:class (stl/css :item-name)}
(if (contains? layout :scale-text)

View File

@ -281,7 +281,7 @@
;; NOTE: this teoretically breaks hooks rules, but in practice
;; it is imposible to really break it
maybe-zoom
(when (cf/check-browser? :safari)
(when (cf/check-browser? :safari-16)
(mf/deref refs/selected-zoom))
shape (cond-> shape
@ -300,26 +300,27 @@
width (mth/max (dm/get-prop bounds :width)
(dm/get-prop shape :width))
height (mth/max (dm/get-prop bounds :height)
(dm/get-prop shape :height))]
(dm/get-prop shape :height))
style
(cond-> #js {:pointer-events "all"}
(cf/check-browser? :safari-16)
(obj/merge!
#js {:position "fixed"
:left 0
:top (- (dm/get-prop shape :y) y)
:transform-origin "top left"
:transform (when (some? maybe-zoom)
(dm/fmt "scale(%)" maybe-zoom))}))]
[:g.text-editor {:clip-path (dm/fmt "url(#%)" clip-id)
:transform (dm/str (gsh/transform-matrix shape))}
[:defs
[:clipPath {:id clip-id}
[:rect {:x x
:y y
:width width
:height height
:fill "red"}]]]
[:rect {:x x :y y :width width :height height}]]]
[:foreignObject {:x x :y y :width width :height height}
[:div {:style {:position "fixed"
:left 0
:top (- (dm/get-prop shape :y) y)
:pointer-events "all"
:transform-origin "top left"
:transform (when (some? maybe-zoom)
(dm/fmt "scale(%)" maybe-zoom))}}
[:div {:style style}
[:& text-shape-edit-html
{:shape shape
:key (dm/str shape-id)}]]]]))

View File

@ -19,11 +19,13 @@
[app.main.ui.workspace.right-header :refer [right-header]]
[app.main.ui.workspace.sidebar.assets :refer [assets-toolbox]]
[app.main.ui.workspace.sidebar.debug :refer [debug-panel]]
[app.main.ui.workspace.sidebar.debug-shape-info :refer [debug-shape-info]]
[app.main.ui.workspace.sidebar.history :refer [history-toolbox]]
[app.main.ui.workspace.sidebar.layers :refer [layers-toolbox]]
[app.main.ui.workspace.sidebar.options :refer [options-toolbox]]
[app.main.ui.workspace.sidebar.shortcuts :refer [shortcuts-container]]
[app.main.ui.workspace.sidebar.sitemap :refer [sitemap]]
[app.util.debug :as dbg]
[app.util.i18n :refer [tr]]
[app.util.object :as obj]
[rumext.v2 :as mf]))
@ -134,10 +136,11 @@
current-section* (mf/use-state :info)
current-section (deref current-section*)
can-be-expanded? (and (not is-comments?)
(not is-history?)
is-inspect?
(= current-section :code))
can-be-expanded? (or (dbg/enabled? :shape-panel)
(and (not is-comments?)
(not is-history?)
is-inspect?
(= current-section :code)))
{:keys [on-pointer-down on-lost-pointer-capture on-pointer-move set-size size]}
(use-resize-hook :code 276 276 768 :x true :right)
@ -176,6 +179,9 @@
[:div {:class (stl/css :settings-bar-inside)}
(cond
(dbg/enabled? :shape-panel)
[:& debug-shape-info]
(true? is-comments?)
[:& comments-sidebar]

View File

@ -60,6 +60,7 @@ $width-settings-bar-max: $s-500;
height: 100%;
display: flex;
flex-direction: column;
z-index: 0;
&.not-expand {
max-width: $width-settings-bar;
}

View File

@ -0,0 +1,101 @@
;; 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 app.main.ui.workspace.sidebar.debug-shape-info
(:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.matrix :as gmt]
[app.main.data.workspace :as dw]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.icons :as i]
[debug :as dbg]
[rumext.v2 :as mf]))
(def remove-attrs
#{:id :name})
(def vertical-layout-attrs
#{})
(def custom-renderer
{:parent-id :shape-link
:frame-id :shape-link
:shapes :shape-list
:shape-ref :shape-link
:transform :matrix-render
:transform-inverse :matrix-render
:selrect :rect-render
:points :points-render})
(mf/defc shape-link
[{:keys [id objects]}]
[:a {:class (stl/css :shape-link)
:on-click #(st/emit! (dw/select-shape id))}
(dm/str (dm/get-in objects [id :name]) " #" id)])
(mf/defc debug-shape-attr
[{:keys [attr value objects]}]
(case (get custom-renderer attr)
:shape-link
[:& shape-link {:id value :objects objects}]
:shape-list
[:div {:class (stl/css :shape-list)}
(for [id value]
[:& shape-link {:id id :objects objects}])]
:matrix-render
[:div (dm/str (gmt/format-precision value 2))]
:rect-render
[:div (dm/fmt "X:% Y:% W:% H:%" (:x value) (:y value) (:width value) (:height value))]
:points-render
[:div {:class (stl/css :point-list)}
(for [point value]
[:div (dm/fmt "(%, %)" (:x point) (:y point))])]
[:div {:class (stl/css :attrs-container-value)} (str value)]))
(mf/defc debug-shape-info
[]
(let [objects (mf/deref refs/workspace-page-objects)
selected (->> (mf/deref refs/selected-shapes)
(map (d/getf objects)))]
[:div {:class (stl/css :shape-info)}
[:div {:class (stl/css :shape-info-title)}
[:span "Debug"]
[:div {:class (stl/css :close-button)
:on-click #(dbg/disable! :shape-panel)}
i/close-refactor]]
(if (empty? selected)
[:div {:class (stl/css :attrs-container)} "No shapes selected"]
(for [[idx current] (d/enumerate selected)]
[:div {:class (stl/css :attrs-container) :key (dm/str "shape" idx)}
[:div {:class (stl/css :shape-title)}
[:div {:class (stl/css :shape-name)} (:name current)]
[:button {:on-click #(debug/dump-object (dm/str (:id current)))} "object"]
[:button {:on-click #(debug/dump-subtree (dm/str (:id current)) true)} "tree"]]
[:div {:class (stl/css :shape-attrs)}
(let [attrs (->> (keys current)
(remove remove-attrs))
attrs (concat [:frame-id :parent-id :shapes]
(->> attrs (remove #{:frame-id :parent-id :shapes})))]
(for [attr attrs]
(when-let [value (get current attr)]
[:div {:class (stl/css-case :attrs-container-attr true
:vertical-layout (contains? vertical-layout-attrs attr))
:key (dm/str "att-" idx "-" attr)}
[:div {:class (stl/css :attrs-container-name)} (d/name attr)]
[:& debug-shape-attr {:attr attr :value value :objects objects}]])))]]))]))

View File

@ -0,0 +1,98 @@
// 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
@import "refactor/common-refactor.scss";
.shape-info {
display: flex;
flex-direction: column;
background-color: var(--panel-background-color);
color: white;
font-size: $fs-12;
}
.shape-info-title {
@include flexCenter;
@include tabTitleTipography;
position: relative;
height: $s-32;
min-height: $s-32;
margin: $s-8 $s-8 0 $s-8;
border-radius: $br-8;
background-color: var(--panel-title-background-color);
span {
@include flexCenter;
flex-grow: 1;
color: var(--title-foreground-color-hover);
}
}
.close-button {
@extend .button-tertiary;
position: absolute;
right: $s-2;
top: $s-2;
height: $s-28;
width: $s-28;
border-radius: $br-6;
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
}
}
.attrs-container {
padding: $s-16 $s-8;
overflow: hidden;
}
.shape-title {
font-size: $fs-14;
padding-bottom: $s-4;
background: $db-cuaternary;
color: $df-primary;
padding: $s-8;
border-radius: $s-8;
display: flex;
gap: $s-4;
}
.shape-name {
flex: 1;
}
.attrs-container-attr {
display: grid;
grid-template-columns: 25% auto;
padding: $s-4 0;
&.vertical-layout {
grid-template-columns: auto;
grid-template-rows: auto 1fr;
}
}
.shape-attrs {
overflow: auto;
height: calc(100% - 8px);
padding-bottom: 8px;
}
.shape-link {
color: $df-primary;
text-decoration: underline;
}
.shape-list {
display: flex;
flex-direction: column;
gap: $s-4;
}
.point-list {
display: flex;
gap: $s-8;
}

View File

@ -508,7 +508,7 @@
[:div {:class (stl/css :component-name)} (if multi
(tr "settings.multiple")
shape-name)]
(cfh/last-path shape-name))]
(when show-menu?
[:div {:class (stl/css :component-actions)}
[:button {:class (stl/css :menu-btn)

View File

@ -40,6 +40,7 @@
display: flex;
align-items: center;
color: var(--title-foreground-color);
margin-right: $s-8;
}
.component-icon {
@ -65,7 +66,6 @@
.component-parent-name {
@include titleTipography;
@include textEllipsis;
direction: rtl;
text-align: left;
max-width: 95%;
padding-left: $s-36;

View File

@ -377,8 +377,8 @@
[:clipPath {:id "clip-handlers"}
[:rect {:x (+ (:x vbox) rule-area-size)
:y (+ (:y vbox) rule-area-size)
:width (max 0 (- (:width vbox) (* rule-area-size 2)))
:height (max 0 (- (:height vbox) (* rule-area-size 2)))}]]]
:width (max 0 (- (:width vbox) rule-area-size))
:height (max 0 (- (:height vbox) rule-area-size))}]]]
[:g {:style {:pointer-events (if disable-events? "none" "auto")}}
(when show-text-editor?
@ -539,12 +539,6 @@
[:& presence/active-cursors
{:page-id page-id}])
[:& scroll-bars/viewport-scrollbars
{:objects base-objects
:zoom zoom
:vbox vbox
:bottom-padding (when palete-size (+ palete-size 8))}]
(when-not hide-ui?
[:& rules/rules
{:zoom zoom
@ -637,4 +631,10 @@
:objects base-objects
:modifiers modifiers
:shape frame
:view-only true}]))]]]]))
:view-only true}]))
[:& scroll-bars/viewport-scrollbars
{:objects base-objects
:zoom zoom
:vbox vbox
:bottom-padding (when palete-size (+ palete-size 8))}]]]]]))

View File

@ -114,6 +114,7 @@
position: absolute;
top: $s-44;
left: 50%;
z-index: $z-index-20;
.grid-actions-container {
@include flexRow;

View File

@ -7,6 +7,7 @@
(ns app.main.ui.workspace.viewport.pixel-overlay
(:require
[app.common.math :as mth]
[app.config :as cfg]
[app.main.data.modal :as modal]
[app.main.data.workspace.colors :as dwc]
[app.main.data.workspace.undo :as dwu]
@ -99,7 +100,9 @@
;; I don't know why, but the zoom view is offset by 24px
;; instead of 25.
sx (- x 32)
sy (- y 17)
;; Safari has a different offset fro the y coord
sy (if (cfg/check-browser? :safari) y (- y 17))
sw 65
sh 35
dx 0

View File

@ -11,6 +11,7 @@
position: absolute;
top: $s-44;
left: 50%;
z-index: $z-index-20;
.viewport-actions-container {
@include flexRow;

View File

@ -77,7 +77,10 @@
:grid-layout
;; Show an overlay to the grid cells to know its properties
:grid-cells})
:grid-cells
;; Show info about shapes
:shape-panel})
(defn enable!
[option]

View File

@ -728,7 +728,10 @@
:method :get})
(rx/map :body)
(rx/mapcat (fn [file]
(->> (rp/cmd! ::sse/import-binfile {:file file :project-id project-id})
(->> (rp/cmd! ::sse/import-binfile
{:name (str/replace (:name data) #".penpot$" "")
:file file
:project-id project-id})
(rx/tap (fn [event]
(let [payload (sse/get-payload event)
type (sse/get-type event)]

View File

@ -57,14 +57,14 @@
:app.main.data.websocket/send-message
:app.main.data.workspace.selection/change-hover-state})
(defn- enable!
(defn enable!
[option]
(dbg/enable! option)
(when (= :events option)
(set! st/*debug-events* true))
(js* "app.main.reinit()"))
(defn- disable!
(defn disable!
[option]
(dbg/disable! option)
(when (= :events option)