mirror of
https://github.com/penpot/penpot.git
synced 2026-09-11 22:49:30 +00:00
Merge remote-tracking branch 'origin/staging' into staging-render
This commit is contained in:
commit
45665a3c21
16
.github/workflows/build-tag.yml
vendored
16
.github/workflows/build-tag.yml
vendored
@ -21,6 +21,22 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
gh_ref: ${{ github.ref_name }}
|
gh_ref: ${{ github.ref_name }}
|
||||||
|
|
||||||
|
notify:
|
||||||
|
name: Notifications
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
needs: build-docker
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Notify Mattermost
|
||||||
|
uses: mattermost/action-mattermost-notify@master
|
||||||
|
with:
|
||||||
|
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK }}
|
||||||
|
MATTERMOST_CHANNEL: bot-alerts-cicd
|
||||||
|
TEXT: |
|
||||||
|
🐳 *[PENPOT] Docker image available.*
|
||||||
|
🔗 Run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||||
|
@infra
|
||||||
|
|
||||||
publish-final-tag:
|
publish-final-tag:
|
||||||
if: ${{ !contains(github.ref_name, '-RC') && !contains(github.ref_name, '-alpha') && !contains(github.ref_name, '-beta') && contains(github.ref_name, '.') }}
|
if: ${{ !contains(github.ref_name, '-RC') && !contains(github.ref_name, '-alpha') && !contains(github.ref_name, '-beta') && contains(github.ref_name, '.') }}
|
||||||
needs: build-docker
|
needs: build-docker
|
||||||
|
|||||||
@ -92,6 +92,7 @@ example. It's still usable as before, we just removed the example.
|
|||||||
- Fix U and E icon displayed in project list [Taiga #12806](https://tree.taiga.io/project/penpot/issue/12806)
|
- Fix U and E icon displayed in project list [Taiga #12806](https://tree.taiga.io/project/penpot/issue/12806)
|
||||||
- Fix unpublish library modal not scrolling a long file list [Taiga #12285](https://tree.taiga.io/project/penpot/issue/12285)
|
- Fix unpublish library modal not scrolling a long file list [Taiga #12285](https://tree.taiga.io/project/penpot/issue/12285)
|
||||||
- Fix incorrect interaction betwen hower and scroll on assets sidebar [Taiga #12389](https://tree.taiga.io/project/penpot/issue/12389)
|
- Fix incorrect interaction betwen hower and scroll on assets sidebar [Taiga #12389](https://tree.taiga.io/project/penpot/issue/12389)
|
||||||
|
- Fix switch variants with paths [Taiga #12841](https://tree.taiga.io/project/penpot/issue/12841)
|
||||||
|
|
||||||
## 2.11.1
|
## 2.11.1
|
||||||
|
|
||||||
|
|||||||
@ -12,8 +12,11 @@
|
|||||||
[app.common.files.changes-builder :as pcb]
|
[app.common.files.changes-builder :as pcb]
|
||||||
[app.common.files.helpers :as cfh]
|
[app.common.files.helpers :as cfh]
|
||||||
[app.common.files.variant :as cfv]
|
[app.common.files.variant :as cfv]
|
||||||
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
|
[app.common.geom.rect :as grc]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
|
[app.common.geom.shapes.common :as gco]
|
||||||
[app.common.logging :as log]
|
[app.common.logging :as log]
|
||||||
[app.common.logic.shapes :as cls]
|
[app.common.logic.shapes :as cls]
|
||||||
[app.common.logic.variant-properties :as clvp]
|
[app.common.logic.variant-properties :as clvp]
|
||||||
@ -26,6 +29,7 @@
|
|||||||
[app.common.types.library :as ctl]
|
[app.common.types.library :as ctl]
|
||||||
[app.common.types.page :as ctp]
|
[app.common.types.page :as ctp]
|
||||||
[app.common.types.pages-list :as ctpl]
|
[app.common.types.pages-list :as ctpl]
|
||||||
|
[app.common.types.path.segment :as segment]
|
||||||
[app.common.types.shape :as cts]
|
[app.common.types.shape :as cts]
|
||||||
[app.common.types.shape-tree :as ctst]
|
[app.common.types.shape-tree :as ctst]
|
||||||
[app.common.types.shape.interactions :as ctsi]
|
[app.common.types.shape.interactions :as ctsi]
|
||||||
@ -1876,6 +1880,44 @@
|
|||||||
roperations'
|
roperations'
|
||||||
uoperations')))))))
|
uoperations')))))))
|
||||||
|
|
||||||
|
(defn- set-path-new-values
|
||||||
|
[current-shape prev-shape transform]
|
||||||
|
(let [new-content (segment/transform-content
|
||||||
|
(:content current-shape)
|
||||||
|
(gmt/transform-in (gpt/point 0 0) transform))
|
||||||
|
new-points (-> (segment/content->selrect new-content)
|
||||||
|
(grc/rect->points))
|
||||||
|
points-center (gco/points->center new-points)
|
||||||
|
new-selrect (gsh/calculate-selrect new-points points-center)
|
||||||
|
shape (assoc current-shape
|
||||||
|
:content new-content
|
||||||
|
:points new-points
|
||||||
|
:selrect new-selrect)
|
||||||
|
|
||||||
|
prev-center (segment/content-center (:content prev-shape))
|
||||||
|
delta (gpt/subtract points-center (first new-points))
|
||||||
|
new-pos (gpt/subtract prev-center delta)]
|
||||||
|
(gsh/absolute-move shape new-pos)))
|
||||||
|
|
||||||
|
(defn- switch-path-change-value
|
||||||
|
[prev-shape ;; The shape before the switch
|
||||||
|
current-shape ;; The shape after the switch (a clean copy)
|
||||||
|
ref-shape ;; The referenced shape on the main component
|
||||||
|
;; before the switch
|
||||||
|
attr]
|
||||||
|
(let [old-width (-> ref-shape :selrect :width)
|
||||||
|
new-width (-> prev-shape :selrect :width)
|
||||||
|
|
||||||
|
old-height (-> ref-shape :selrect :height)
|
||||||
|
new-height (-> prev-shape :selrect :height)
|
||||||
|
|
||||||
|
transform (-> (gpt/point (/ new-width old-width)
|
||||||
|
(/ new-height old-height))
|
||||||
|
(gmt/scale-matrix))
|
||||||
|
|
||||||
|
shape (set-path-new-values current-shape prev-shape transform)]
|
||||||
|
(get shape attr)))
|
||||||
|
|
||||||
|
|
||||||
(defn- switch-text-change-value
|
(defn- switch-text-change-value
|
||||||
[prev-content ;; The :content of the text before the switch
|
[prev-content ;; The :content of the text before the switch
|
||||||
@ -2027,6 +2069,10 @@
|
|||||||
(= :content attr)
|
(= :content attr)
|
||||||
(touched attr-group))
|
(touched attr-group))
|
||||||
|
|
||||||
|
path-change?
|
||||||
|
(and (= :path (:type current-shape))
|
||||||
|
(contains? #{:points :selrect :content} attr))
|
||||||
|
|
||||||
;; position-data is a special case because can be affected by :geometry-group and :content-group
|
;; position-data is a special case because can be affected by :geometry-group and :content-group
|
||||||
;; so, if the position-data changes but the geometry is touched we need to reset the position-data
|
;; so, if the position-data changes but the geometry is touched we need to reset the position-data
|
||||||
;; so it's calculated again
|
;; so it's calculated again
|
||||||
@ -2055,6 +2101,12 @@
|
|||||||
(:content origin-ref-shape)
|
(:content origin-ref-shape)
|
||||||
touched)
|
touched)
|
||||||
|
|
||||||
|
path-change?
|
||||||
|
(switch-path-change-value previous-shape
|
||||||
|
current-shape
|
||||||
|
origin-ref-shape
|
||||||
|
attr)
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(get previous-shape attr)))
|
(get previous-shape attr)))
|
||||||
|
|
||||||
|
|||||||
@ -281,7 +281,20 @@
|
|||||||
(defn check-fn
|
(defn check-fn
|
||||||
"Create a predefined check function"
|
"Create a predefined check function"
|
||||||
[s & {:keys [hint type code]}]
|
[s & {:keys [hint type code]}]
|
||||||
(let [s (schema s)
|
(let [s #?(:clj
|
||||||
|
(schema s)
|
||||||
|
:cljs
|
||||||
|
(try
|
||||||
|
(schema s)
|
||||||
|
(catch :default cause
|
||||||
|
(let [data (ex-data cause)]
|
||||||
|
(if (= :malli.core/invalid-schema (:type data))
|
||||||
|
(throw (ex-info
|
||||||
|
(str "Invalid schema\n"
|
||||||
|
(pp/pprint-str (:data data)))
|
||||||
|
{}))
|
||||||
|
(throw cause))))))
|
||||||
|
|
||||||
validator* (delay (m/validator s))
|
validator* (delay (m/validator s))
|
||||||
explainer* (delay (m/explainer s))
|
explainer* (delay (m/explainer s))
|
||||||
hint (or ^boolean hint "check error")
|
hint (or ^boolean hint "check error")
|
||||||
|
|||||||
@ -7,4 +7,5 @@ bb -i '(babashka.wait/wait-for-port "localhost" 9630)';
|
|||||||
bb -i '(babashka.wait/wait-for-path "target/app.js")';
|
bb -i '(babashka.wait/wait-for-path "target/app.js")';
|
||||||
sleep 2;
|
sleep 2;
|
||||||
|
|
||||||
|
export NODE_TLS_REJECT_UNAUTHORIZED=0
|
||||||
exec node target/app.js
|
exec node target/app.js
|
||||||
|
|||||||
@ -100,7 +100,7 @@
|
|||||||
|
|
||||||
(def browser-pool-factory
|
(def browser-pool-factory
|
||||||
(letfn [(create []
|
(letfn [(create []
|
||||||
(p/let [opts #js {:args #js ["--font-render-hinting=none"]}
|
(p/let [opts #js {:args #js ["--allow-insecure-localhost" "--font-render-hinting=none"]}
|
||||||
browser (.launch pw/chromium opts)
|
browser (.launch pw/chromium opts)
|
||||||
id (swap! pool-browser-id inc)]
|
id (swap! pool-browser-id inc)]
|
||||||
(l/info :origin "factory" :action "create" :browser-id id)
|
(l/info :origin "factory" :action "create" :browser-id id)
|
||||||
|
|||||||
@ -74,7 +74,7 @@
|
|||||||
(p/fmap (fn [resource]
|
(p/fmap (fn [resource]
|
||||||
(assoc exchange :response/body resource)))
|
(assoc exchange :response/body resource)))
|
||||||
(p/merr (fn [cause]
|
(p/merr (fn [cause]
|
||||||
(l/error :hint "unexpected error on export multiple"
|
(l/error :hint "unexpected error on single export"
|
||||||
:cause cause)
|
:cause cause)
|
||||||
(p/rejected cause))))))
|
(p/rejected cause))))))
|
||||||
|
|
||||||
@ -94,7 +94,7 @@
|
|||||||
(redis/pub! topic data))))
|
(redis/pub! topic data))))
|
||||||
|
|
||||||
on-error (fn [cause]
|
on-error (fn [cause]
|
||||||
(l/error :hint "unexpected error on multiple exportation" :cause cause)
|
(l/error :hint "unexpected error on multiple export" :cause cause)
|
||||||
(if wait
|
(if wait
|
||||||
(p/rejected cause)
|
(p/rejected cause)
|
||||||
(redis/pub! topic {:type :export-update
|
(redis/pub! topic {:type :export-update
|
||||||
|
|||||||
@ -106,7 +106,7 @@
|
|||||||
"@penpot/hljs": "portal:./vendor/hljs",
|
"@penpot/hljs": "portal:./vendor/hljs",
|
||||||
"@penpot/mousetrap": "portal:./vendor/mousetrap",
|
"@penpot/mousetrap": "portal:./vendor/mousetrap",
|
||||||
"@penpot/plugins-runtime": "1.3.2",
|
"@penpot/plugins-runtime": "1.3.2",
|
||||||
"@penpot/svgo": "penpot/svgo#v3.1",
|
"@penpot/svgo": "penpot/svgo#v3.2",
|
||||||
"@penpot/text-editor": "portal:./text-editor",
|
"@penpot/text-editor": "portal:./text-editor",
|
||||||
"@tokens-studio/sd-transforms": "1.2.11",
|
"@tokens-studio/sd-transforms": "1.2.11",
|
||||||
"@zip.js/zip.js": "patch:@zip.js/zip.js@npm%3A2.7.60#~/.yarn/patches/@zip.js-zip.js-npm-2.7.60-b6b814410b.patch",
|
"@zip.js/zip.js": "patch:@zip.js/zip.js@npm%3A2.7.60#~/.yarn/patches/@zip.js-zip.js-npm-2.7.60-b6b814410b.patch",
|
||||||
|
|||||||
@ -351,19 +351,31 @@
|
|||||||
(on-success))))
|
(on-success))))
|
||||||
(rx/catch on-error))))))
|
(rx/catch on-error))))))
|
||||||
|
|
||||||
|
|
||||||
|
(def ^:private schema:create-invitation
|
||||||
|
[:and
|
||||||
|
[:map
|
||||||
|
[:emails {:optional true} [::sm/set ::sm/email]]
|
||||||
|
[:invitations {:optional true}
|
||||||
|
[:vector
|
||||||
|
[:map
|
||||||
|
[:email ::sm/email]
|
||||||
|
[:role [::sm/one-of ctt/valid-roles]]]]]
|
||||||
|
[:team-id ::sm/uuid]
|
||||||
|
[:resend? {:optional true} ::sm/boolean]]
|
||||||
|
[:fn (fn [attrs]
|
||||||
|
(or (contains? attrs :emails)
|
||||||
|
(contains? attrs :invitations)))]])
|
||||||
|
|
||||||
|
(def ^:private check-create-invitations-params
|
||||||
|
(sm/check-fn schema:create-invitation))
|
||||||
|
|
||||||
(defn create-invitations
|
(defn create-invitations
|
||||||
"Unified function to create invitations. Supports two parameter formats:
|
"Unified function to create invitations. Supports two parameter formats:
|
||||||
1. {:emails #{...} :role :admin :team-id uuid} - single role for all emails
|
1. {:emails #{...} :role :admin :team-id uuid} - single role for all emails
|
||||||
2. {:invitations [{:email ... :role ...}] :team-id uuid} - individual roles per email"
|
2. {:invitations [{:email ... :role ...}] :team-id uuid} - individual roles per email"
|
||||||
[{:keys [emails role team-id invitations resend?] :as params}]
|
[{:keys [emails role team-id invitations resend?] :as params}]
|
||||||
|
(check-create-invitations-params params)
|
||||||
(assert (uuid? team-id))
|
|
||||||
;; Validate input format - must have either emails+role OR invitations
|
|
||||||
(assert (or (and emails role (sm/check-set-of-emails emails) (keyword? role))
|
|
||||||
(and invitations
|
|
||||||
(sm/check-set-of-emails (map :email invitations))
|
|
||||||
(every? #(contains? ctt/valid-roles (:role %)) invitations)))
|
|
||||||
"Must provide either emails+role or invitations with individual roles")
|
|
||||||
|
|
||||||
(ptk/reify ::create-invitations
|
(ptk/reify ::create-invitations
|
||||||
ev/Event
|
ev/Event
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
:text [:visibility :geometry :text :shadow :blur :stroke :layout-element]
|
:text [:visibility :geometry :text :shadow :blur :stroke :layout-element]
|
||||||
:variant [:variant :geometry :fill :stroke :shadow :blur :layout :layout-element]})
|
:variant [:variant :geometry :fill :stroke :shadow :blur :layout :layout-element]})
|
||||||
|
|
||||||
(mf/defc attributes
|
(mf/defc attributes*
|
||||||
[{:keys [page-id file-id shapes frame from libraries share-id objects color-space]}]
|
[{:keys [page-id file-id shapes frame from libraries share-id objects color-space]}]
|
||||||
(let [shapes (hooks/use-equal-memo shapes)
|
(let [shapes (hooks/use-equal-memo shapes)
|
||||||
first-shape (first shapes)
|
first-shape (first shapes)
|
||||||
|
|||||||
@ -96,7 +96,7 @@
|
|||||||
embed-images? (replace-map images-data))]
|
embed-images? (replace-map images-data))]
|
||||||
(str/format page-template style-code markup-code)))
|
(str/format page-template style-code markup-code)))
|
||||||
|
|
||||||
(mf/defc code
|
(mf/defc code*
|
||||||
[{:keys [shapes frame on-expand from]}]
|
[{:keys [shapes frame on-expand from]}]
|
||||||
(let [style-type* (mf/use-state "css")
|
(let [style-type* (mf/use-state "css")
|
||||||
markup-type* (mf/use-state "html")
|
markup-type* (mf/use-state "html")
|
||||||
|
|||||||
@ -16,8 +16,8 @@
|
|||||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
|
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
|
||||||
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
||||||
[app.main.ui.icons :as deprecated-icon]
|
[app.main.ui.icons :as deprecated-icon]
|
||||||
[app.main.ui.inspect.attributes :refer [attributes]]
|
[app.main.ui.inspect.attributes :refer [attributes*]]
|
||||||
[app.main.ui.inspect.code :refer [code]]
|
[app.main.ui.inspect.code :refer [code*]]
|
||||||
[app.main.ui.inspect.selection-feedback :refer [resolve-shapes]]
|
[app.main.ui.inspect.selection-feedback :refer [resolve-shapes]]
|
||||||
[app.main.ui.inspect.styles :refer [styles-tab*]]
|
[app.main.ui.inspect.styles :refer [styles-tab*]]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
@ -122,8 +122,7 @@
|
|||||||
(fn []
|
(fn []
|
||||||
(if (seq shapes)
|
(if (seq shapes)
|
||||||
(st/emit! (ptk/event ::ev/event {::ev/name "inspect-mode-click-element"}))
|
(st/emit! (ptk/event ::ev/event {::ev/name "inspect-mode-click-element"}))
|
||||||
(handle-change-tab (if (contains? cf/flags :inspect-styles) :styles :info)))
|
(handle-change-tab (if (contains? cf/flags :inspect-styles) :styles :info)))))
|
||||||
(reset! color-space* "hex")))
|
|
||||||
|
|
||||||
[:aside {:class (stl/css-case :settings-bar-right true
|
[:aside {:class (stl/css-case :settings-bar-right true
|
||||||
:viewer-code (= from :viewer))}
|
:viewer-code (= from :viewer))}
|
||||||
@ -189,41 +188,41 @@
|
|||||||
:libraries libraries
|
:libraries libraries
|
||||||
:file-id file-id}]
|
:file-id file-id}]
|
||||||
:computed
|
:computed
|
||||||
[:& attributes {:color-space color-space
|
[:> attributes* {:color-space color-space
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:objects objects
|
:objects objects
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
:frame frame
|
:frame frame
|
||||||
:shapes shapes
|
:shapes shapes
|
||||||
:from from
|
:from from
|
||||||
:libraries libraries
|
:libraries libraries
|
||||||
:share-id share-id}]
|
:share-id share-id}]
|
||||||
|
|
||||||
:code
|
:code
|
||||||
[:& code {:frame frame
|
[:> code* {:frame frame
|
||||||
:shapes shapes
|
:shapes shapes
|
||||||
:on-expand handle-expand
|
:on-expand handle-expand
|
||||||
:from from}])]
|
:from from}])]
|
||||||
[:> tab-switcher* {:tabs tabs
|
[:> tab-switcher* {:tabs tabs
|
||||||
:selected (name @section)
|
:selected (name @section)
|
||||||
:on-change handle-change-tab
|
:on-change handle-change-tab
|
||||||
:class (stl/css :viewer-tab-switcher)}
|
:class (stl/css :viewer-tab-switcher)}
|
||||||
(case @section
|
(case @section
|
||||||
:info
|
:info
|
||||||
[:& attributes {:page-id page-id
|
[:> attributes* {:page-id page-id
|
||||||
:objects objects
|
:objects objects
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
:frame frame
|
:frame frame
|
||||||
:shapes shapes
|
:shapes shapes
|
||||||
:from from
|
:from from
|
||||||
:libraries libraries
|
:libraries libraries
|
||||||
:share-id share-id}]
|
:share-id share-id}]
|
||||||
|
|
||||||
:code
|
:code
|
||||||
[:& code {:frame frame
|
[:> code* {:frame frame
|
||||||
:shapes shapes
|
:shapes shapes
|
||||||
:on-expand handle-expand
|
:on-expand handle-expand
|
||||||
:from from}])])]]
|
:from from}])])]]
|
||||||
[:div {:class (stl/css :empty)}
|
[:div {:class (stl/css :empty)}
|
||||||
[:div {:class (stl/css :code-info)}
|
[:div {:class (stl/css :code-info)}
|
||||||
[:span {:class (stl/css :placeholder-icon)}
|
[:span {:class (stl/css :placeholder-icon)}
|
||||||
|
|||||||
@ -133,7 +133,7 @@
|
|||||||
(swap! shorthands* assoc (:panel shorthand) (:property shorthand))))]
|
(swap! shorthands* assoc (:panel shorthand) (:property shorthand))))]
|
||||||
[:ol {:class (stl/css :styles-tab) :aria-label (tr "labels.styles")}
|
[:ol {:class (stl/css :styles-tab) :aria-label (tr "labels.styles")}
|
||||||
;; TOKENS PANEL
|
;; TOKENS PANEL
|
||||||
(when (or active-themes active-sets)
|
(when (or (seq active-themes) (seq active-sets))
|
||||||
[:li
|
[:li
|
||||||
[:> style-box* {:panel :token}
|
[:> style-box* {:panel :token}
|
||||||
[:> tokens-panel* {:theme-paths active-themes :set-names active-sets}]]])
|
[:> tokens-panel* {:theme-paths active-themes :set-names active-sets}]]])
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
[app.main.ui.workspace.coordinates :as coordinates]
|
[app.main.ui.workspace.coordinates :as coordinates]
|
||||||
[app.main.ui.workspace.libraries]
|
[app.main.ui.workspace.libraries]
|
||||||
[app.main.ui.workspace.nudge]
|
[app.main.ui.workspace.nudge]
|
||||||
[app.main.ui.workspace.palette :refer [palette]]
|
[app.main.ui.workspace.palette :refer [palette*]]
|
||||||
[app.main.ui.workspace.plugins]
|
[app.main.ui.workspace.plugins]
|
||||||
[app.main.ui.workspace.sidebar :refer [sidebar*]]
|
[app.main.ui.workspace.sidebar :refer [sidebar*]]
|
||||||
[app.main.ui.workspace.sidebar.history :refer [history-toolbox*]]
|
[app.main.ui.workspace.sidebar.history :refer [history-toolbox*]]
|
||||||
@ -84,8 +84,8 @@
|
|||||||
node-ref (use-resize-observer on-resize)]
|
node-ref (use-resize-observer on-resize)]
|
||||||
[:*
|
[:*
|
||||||
(when (not ^boolean hide-ui?)
|
(when (not ^boolean hide-ui?)
|
||||||
[:& palette {:layout layout
|
[:> palette* {:layout layout
|
||||||
:on-change-palette-size on-resize-palette}])
|
:on-change-size on-resize-palette}])
|
||||||
|
|
||||||
[:section
|
[:section
|
||||||
{:key (dm/str "workspace-" page-id)
|
{:key (dm/str "workspace-" page-id)
|
||||||
|
|||||||
@ -156,7 +156,7 @@
|
|||||||
(let [{:keys [modal title]} (get dwta/token-properties :color)
|
(let [{:keys [modal title]} (get dwta/token-properties :color)
|
||||||
window-size (dom/get-window-size)
|
window-size (dom/get-window-size)
|
||||||
left-sidebar (dom/get-element "left-sidebar-aside")
|
left-sidebar (dom/get-element "left-sidebar-aside")
|
||||||
x-size (dom/get-data left-sidebar "left-sidebar-width")
|
x-size (dom/get-data left-sidebar "width")
|
||||||
modal-height 392
|
modal-height 392
|
||||||
x (- (int x-size) 30)
|
x (- (int x-size) 30)
|
||||||
y (- (/ (:height window-size) 2) (/ modal-height 2))]
|
y (- (/ (:height window-size) 2) (/ modal-height 2))]
|
||||||
|
|||||||
@ -33,12 +33,13 @@
|
|||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(def viewport
|
(def ^:private ref:viewport
|
||||||
(l/derived :vport refs/workspace-local))
|
(l/derived :vport refs/workspace-local))
|
||||||
|
|
||||||
(defn calculate-palette-padding [rulers?]
|
(defn- calculate-palette-style
|
||||||
|
[rulers?]
|
||||||
(let [left-sidebar (dom/get-element "left-sidebar-aside")
|
(let [left-sidebar (dom/get-element "left-sidebar-aside")
|
||||||
left-sidebar-size (-> (dom/get-data left-sidebar "left-sidebar-width")
|
left-sidebar-size (-> (dom/get-data left-sidebar "width")
|
||||||
(d/parse-integer))
|
(d/parse-integer))
|
||||||
rulers-width (if rulers? 22 0)
|
rulers-width (if rulers? 22 0)
|
||||||
min-left-sidebar-width left-sidebar-default-width
|
min-left-sidebar-width left-sidebar-default-width
|
||||||
@ -48,36 +49,46 @@
|
|||||||
#js {"paddingLeft" (dm/str calculate-padding-left "px")
|
#js {"paddingLeft" (dm/str calculate-padding-left "px")
|
||||||
"paddingRight" "322px"}))
|
"paddingRight" "322px"}))
|
||||||
|
|
||||||
(mf/defc palette
|
(mf/defc palette*
|
||||||
[{:keys [layout on-change-palette-size]}]
|
[{:keys [layout on-change-size]}]
|
||||||
(let [color-palette? (:colorpalette layout)
|
(let [color-palette? (:colorpalette layout)
|
||||||
text-palette? (:textpalette layout)
|
text-palette? (:textpalette layout)
|
||||||
hide-palettes? (:hide-palettes layout)
|
hide-palettes? (:hide-palettes layout)
|
||||||
workspace-read-only? (mf/use-ctx ctx/workspace-read-only?)
|
|
||||||
container (mf/use-ref nil)
|
|
||||||
state* (mf/use-state {:show-menu false})
|
|
||||||
state (deref state*)
|
|
||||||
show-menu? (:show-menu state)
|
|
||||||
selected (h/use-shared-state mdc/colorpalette-selected-broadcast-key :recent)
|
|
||||||
selected-text* (mf/use-state :file)
|
|
||||||
selected-text (deref selected-text*)
|
|
||||||
on-select (mf/use-fn #(reset! selected %))
|
|
||||||
rulers? (mf/deref refs/rulers?)
|
|
||||||
{:keys [on-pointer-down on-lost-pointer-capture on-pointer-move parent-ref size]}
|
|
||||||
(r/use-resize-hook :palette 72 54 80 :y true :bottom on-change-palette-size)
|
|
||||||
|
|
||||||
vport (mf/deref viewport)
|
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||||
vport-width (:width vport)
|
container (mf/use-ref nil)
|
||||||
|
|
||||||
|
state* (mf/use-state #(-> {:show-menu false}))
|
||||||
|
state (deref state*)
|
||||||
|
show-menu? (:show-menu state)
|
||||||
|
|
||||||
|
selected (h/use-shared-state mdc/colorpalette-selected-broadcast-key :recent)
|
||||||
|
|
||||||
|
selected-text* (mf/use-state :file)
|
||||||
|
selected-text (deref selected-text*)
|
||||||
|
|
||||||
|
on-select (mf/use-fn #(reset! selected %))
|
||||||
|
|
||||||
|
rulers? (mf/deref refs/rulers?)
|
||||||
|
vport (mf/deref ref:viewport)
|
||||||
|
vport-width (get vport :width)
|
||||||
|
|
||||||
|
{:keys [on-pointer-down
|
||||||
|
on-lost-pointer-capture
|
||||||
|
on-pointer-move
|
||||||
|
parent-ref
|
||||||
|
size]}
|
||||||
|
(r/use-resize-hook :palette 72 54 80 :y true :bottom on-change-size)
|
||||||
|
|
||||||
on-resize
|
on-resize
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [_]
|
(fn [_]
|
||||||
(let [dom (mf/ref-val container)
|
(let [dom (mf/ref-val container)
|
||||||
width (obj/get dom "clientWidth")]
|
width (obj/get dom "clientWidth")]
|
||||||
(swap! state* assoc :width width))))
|
(swap! state* assoc :width width))))
|
||||||
|
|
||||||
on-close-menu
|
on-close-menu
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [_]
|
(fn [_]
|
||||||
(swap! state* assoc :show-menu false)))
|
(swap! state* assoc :show-menu false)))
|
||||||
|
|
||||||
@ -100,7 +111,7 @@
|
|||||||
(reset! selected-text* (:id lib)))))
|
(reset! selected-text* (:id lib)))))
|
||||||
|
|
||||||
toggle-palettes
|
toggle-palettes
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [_]
|
(fn [_]
|
||||||
(r/set-resize-type! :top)
|
(r/set-resize-type! :top)
|
||||||
(dom/add-class! (dom/get-element-by-class "color-palette") "fade-out-down")
|
(dom/add-class! (dom/get-element-by-class "color-palette") "fade-out-down")
|
||||||
@ -131,7 +142,9 @@
|
|||||||
(vary-meta assoc ::ev/origin "workspace-left-toolbar"))))
|
(vary-meta assoc ::ev/origin "workspace-left-toolbar"))))
|
||||||
(dom/blur! node))))
|
(dom/blur! node))))
|
||||||
|
|
||||||
any-palette? (or color-palette? text-palette?)
|
any-palette?
|
||||||
|
(or color-palette? text-palette?)
|
||||||
|
|
||||||
size-classname
|
size-classname
|
||||||
(cond
|
(cond
|
||||||
(<= size 64) (stl/css :small-palette)
|
(<= size 64) (stl/css :small-palette)
|
||||||
@ -142,16 +155,16 @@
|
|||||||
(let [key1 (events/listen js/window "resize" on-resize)]
|
(let [key1 (events/listen js/window "resize" on-resize)]
|
||||||
#(events/unlistenByKey key1)))
|
#(events/unlistenByKey key1)))
|
||||||
|
|
||||||
(mf/use-layout-effect
|
(mf/with-layout-effect []
|
||||||
#(let [dom (mf/ref-val parent-ref)
|
(let [dom (mf/ref-val parent-ref)
|
||||||
width (obj/get dom "clientWidth")]
|
width (obj/get dom "clientWidth")]
|
||||||
(swap! state* assoc :width width)))
|
(swap! state* assoc :width width)))
|
||||||
|
|
||||||
[:div {:class (stl/css :palette-wrapper)
|
[:div {:class (stl/css :palette-wrapper)
|
||||||
:id "palette-wrapper"
|
:id "palette-wrapper"
|
||||||
:style (calculate-palette-padding rulers?)
|
:style (calculate-palette-style rulers?)
|
||||||
:data-testid "palette"}
|
:data-testid "palette"}
|
||||||
(when-not workspace-read-only?
|
(when-not ^boolean read-only?
|
||||||
[:div {:ref parent-ref
|
[:div {:ref parent-ref
|
||||||
:class (dm/str size-classname " " (stl/css-case :palettes true
|
:class (dm/str size-classname " " (stl/css-case :palettes true
|
||||||
:wide any-palette?
|
:wide any-palette?
|
||||||
|
|||||||
@ -27,7 +27,6 @@
|
|||||||
[app.main.ui.workspace.left-header :refer [left-header*]]
|
[app.main.ui.workspace.left-header :refer [left-header*]]
|
||||||
[app.main.ui.workspace.right-header :refer [right-header*]]
|
[app.main.ui.workspace.right-header :refer [right-header*]]
|
||||||
[app.main.ui.workspace.sidebar.assets :refer [assets-toolbox*]]
|
[app.main.ui.workspace.sidebar.assets :refer [assets-toolbox*]]
|
||||||
[app.main.ui.workspace.sidebar.collapsable-button :refer [collapsed-button*]]
|
|
||||||
[app.main.ui.workspace.sidebar.debug :refer [debug-panel*]]
|
[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.debug-shape-info :refer [debug-shape-info*]]
|
||||||
[app.main.ui.workspace.sidebar.history :refer [history-toolbox*]]
|
[app.main.ui.workspace.sidebar.history :refer [history-toolbox*]]
|
||||||
@ -44,19 +43,34 @@
|
|||||||
|
|
||||||
;; --- Left Sidebar (Component)
|
;; --- Left Sidebar (Component)
|
||||||
|
|
||||||
(defn- on-collapse-left-sidebar
|
(def ^:private toggle-collapse-left-sidebar
|
||||||
[]
|
(partial st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))
|
||||||
(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))
|
|
||||||
|
|
||||||
(mf/defc collapse-button*
|
(mf/defc collapse-button*
|
||||||
|
{::mf/private true}
|
||||||
[]
|
[]
|
||||||
;; NOTE: This custom button may be replace by an action button when this variant is designed
|
;; NOTE: This custom button may be replace by an action button when this variant is designed
|
||||||
[:button {:class (stl/css :collapse-sidebar-button)
|
[:button {:class (stl/css :collapse-sidebar-button)
|
||||||
:on-click on-collapse-left-sidebar}
|
:on-click toggle-collapse-left-sidebar}
|
||||||
[:> icon* {:icon-id i/arrow
|
[:> icon* {:icon-id i/arrow
|
||||||
:size "s"
|
:size "s"
|
||||||
:aria-label (tr "workspace.sidebar.collapse")}]])
|
:aria-label (tr "workspace.sidebar.collapse")}]])
|
||||||
|
|
||||||
|
(mf/defc collapsed-button*
|
||||||
|
{::mf/memo true
|
||||||
|
::mf/private true}
|
||||||
|
[]
|
||||||
|
[:div {:id "left-sidebar-aside"
|
||||||
|
:data-width "0"
|
||||||
|
:class (stl/css :collapsed-sidebar)}
|
||||||
|
[:div {:class (stl/css :collapsed-title)}
|
||||||
|
[:button {:class (stl/css :collapsed-button)
|
||||||
|
:title (tr "workspace.sidebar.expand")
|
||||||
|
:on-click toggle-collapse-left-sidebar}
|
||||||
|
[:> icon* {:icon-id i/arrow
|
||||||
|
:size "s"
|
||||||
|
:aria-label (tr "workspace.sidebar.expand")}]]]])
|
||||||
|
|
||||||
(mf/defc layers-content*
|
(mf/defc layers-content*
|
||||||
{::mf/private true
|
{::mf/private true
|
||||||
::mf/memo true}
|
::mf/memo true}
|
||||||
@ -97,6 +111,7 @@
|
|||||||
|
|
||||||
[:> layers-toolbox* {:size-parent width}]]))
|
[:> layers-toolbox* {:size-parent width}]]))
|
||||||
|
|
||||||
|
|
||||||
(mf/defc left-sidebar*
|
(mf/defc left-sidebar*
|
||||||
{::mf/memo true}
|
{::mf/memo true}
|
||||||
[{:keys [layout file page-id tokens-lib active-tokens resolved-active-tokens]}]
|
[{:keys [layout file page-id tokens-lib active-tokens resolved-active-tokens]}]
|
||||||
@ -161,7 +176,7 @@
|
|||||||
[:aside {:ref parent-ref
|
[:aside {:ref parent-ref
|
||||||
:id "left-sidebar-aside"
|
:id "left-sidebar-aside"
|
||||||
:data-testid "left-sidebar"
|
:data-testid "left-sidebar"
|
||||||
:data-left-sidebar-width (str width)
|
:data-width (str width)
|
||||||
:class aside-class
|
:class aside-class
|
||||||
:style {:--left-sidebar-width (dm/str width "px")}}
|
:style {:--left-sidebar-width (dm/str width "px")}}
|
||||||
|
|
||||||
|
|||||||
@ -116,6 +116,44 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.collapsed-sidebar {
|
||||||
|
@include deprecated.flexCenter;
|
||||||
|
position: absolute;
|
||||||
|
top: deprecated.$s-48;
|
||||||
|
left: 0;
|
||||||
|
padding: deprecated.$s-4;
|
||||||
|
border-radius: deprecated.$br-8;
|
||||||
|
background: var(--color-background-primary);
|
||||||
|
margin-inline-start: var(--sp-m);
|
||||||
|
}
|
||||||
|
.collapsed-title {
|
||||||
|
@include deprecated.flexCenter;
|
||||||
|
height: deprecated.$s-36;
|
||||||
|
width: deprecated.$s-24;
|
||||||
|
border-radius: deprecated.$br-8;
|
||||||
|
background: var(--color-background-secondary);
|
||||||
|
}
|
||||||
|
.collapsed-button {
|
||||||
|
@include deprecated.buttonStyle;
|
||||||
|
height: deprecated.$s-24;
|
||||||
|
width: deprecated.$s-16;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: deprecated.$br-5;
|
||||||
|
svg {
|
||||||
|
@include deprecated.flexCenter;
|
||||||
|
height: deprecated.$s-16;
|
||||||
|
width: deprecated.$s-16;
|
||||||
|
color: transparent;
|
||||||
|
fill: none;
|
||||||
|
stroke: var(--icon-foreground);
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
svg {
|
||||||
|
stroke: var(--icon-foreground-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.versions-tab {
|
.versions-tab {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@ -1,29 +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 app.main.ui.workspace.sidebar.collapsable-button
|
|
||||||
(:require-macros [app.main.style :as stl])
|
|
||||||
(:require
|
|
||||||
[app.main.data.workspace :as dw]
|
|
||||||
[app.main.store :as st]
|
|
||||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
|
|
||||||
[app.util.i18n :refer [tr]]
|
|
||||||
[rumext.v2 :as mf]))
|
|
||||||
|
|
||||||
(mf/defc collapsed-button*
|
|
||||||
{::mf/memo true}
|
|
||||||
[]
|
|
||||||
(let [on-click (mf/use-fn #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))]
|
|
||||||
[:div {:id "left-sidebar-aside"
|
|
||||||
:data-size "0"
|
|
||||||
:class (stl/css :collapsed-sidebar)}
|
|
||||||
[:div {:class (stl/css :collapsed-title)}
|
|
||||||
[:button {:class (stl/css :collapsed-button)
|
|
||||||
:title (tr "workspace.sidebar.expand")
|
|
||||||
:on-click on-click}
|
|
||||||
[:> icon* {:icon-id i/arrow
|
|
||||||
:size "s"
|
|
||||||
:aria-label (tr "workspace.sidebar.expand")}]]]]))
|
|
||||||
@ -1,45 +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
|
|
||||||
|
|
||||||
@use "refactor/common-refactor.scss" as deprecated;
|
|
||||||
|
|
||||||
.collapsed-sidebar {
|
|
||||||
@include deprecated.flexCenter;
|
|
||||||
position: absolute;
|
|
||||||
top: deprecated.$s-48;
|
|
||||||
left: 0;
|
|
||||||
padding: deprecated.$s-4;
|
|
||||||
border-radius: deprecated.$br-8;
|
|
||||||
background: var(--color-background-primary);
|
|
||||||
margin-inline-start: var(--sp-m);
|
|
||||||
}
|
|
||||||
.collapsed-title {
|
|
||||||
@include deprecated.flexCenter;
|
|
||||||
height: deprecated.$s-36;
|
|
||||||
width: deprecated.$s-24;
|
|
||||||
border-radius: deprecated.$br-8;
|
|
||||||
background: var(--color-background-secondary);
|
|
||||||
}
|
|
||||||
.collapsed-button {
|
|
||||||
@include deprecated.buttonStyle;
|
|
||||||
height: deprecated.$s-24;
|
|
||||||
width: deprecated.$s-16;
|
|
||||||
padding: 0;
|
|
||||||
border-radius: deprecated.$br-5;
|
|
||||||
svg {
|
|
||||||
@include deprecated.flexCenter;
|
|
||||||
height: deprecated.$s-16;
|
|
||||||
width: deprecated.$s-16;
|
|
||||||
color: transparent;
|
|
||||||
fill: none;
|
|
||||||
stroke: var(--icon-foreground);
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
svg {
|
|
||||||
stroke: var(--icon-foreground-hover);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -20,15 +20,21 @@
|
|||||||
|
|
||||||
;; Component -------------------------------------------------------------------
|
;; Component -------------------------------------------------------------------
|
||||||
|
|
||||||
(defn calculate-position
|
(defn- calculate-position
|
||||||
"Calculates the style properties for the given coordinates and position"
|
"Calculates the style properties for the given coordinates and position"
|
||||||
[{vh :height} position x y color?]
|
[{vh :height} position x y token-type]
|
||||||
(let [;; picker height in pixels
|
(let [; TODO: Revisit these harcoded values
|
||||||
;; TODO: Revisit these harcoded values
|
modal-height (case token-type
|
||||||
h (if color? 610 510)
|
:color
|
||||||
|
500
|
||||||
|
:typography
|
||||||
|
660
|
||||||
|
:shadow
|
||||||
|
660
|
||||||
|
400)
|
||||||
;; Checks for overflow outside the viewport height
|
;; Checks for overflow outside the viewport height
|
||||||
max-y (- vh h)
|
max-y (- vh modal-height)
|
||||||
overflow-fix (max 0 (+ y (- 50) h (- vh)))
|
overflow-fix (max 0 (+ y (- 50) modal-height (- vh)))
|
||||||
bottom-offset "1rem"
|
bottom-offset "1rem"
|
||||||
top-offset (dm/str (- y 70) "px")
|
top-offset (dm/str (- y 70) "px")
|
||||||
max-height-top (str "calc(100vh - " top-offset)
|
max-height-top (str "calc(100vh - " top-offset)
|
||||||
@ -61,17 +67,19 @@
|
|||||||
:top (dm/str (- y 70 overflow-fix) "px")
|
:top (dm/str (- y 70 overflow-fix) "px")
|
||||||
:maxHeight max-height-top}))))
|
:maxHeight max-height-top}))))
|
||||||
|
|
||||||
(defn use-viewport-position-style [x y position color?]
|
(defn use-viewport-position-style [x y position token-type]
|
||||||
(let [vport (-> (l/derived :vport refs/workspace-local)
|
(let [vport (-> (l/derived :vport refs/workspace-local)
|
||||||
(mf/deref))]
|
(mf/deref))]
|
||||||
(-> (calculate-position vport position x y color?)
|
(-> (calculate-position vport position x y token-type)
|
||||||
(clj->js))))
|
(clj->js))))
|
||||||
|
|
||||||
(mf/defc token-update-create-modal
|
(mf/defc token-update-create-modal
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[{:keys [x y position token token-type action selected-token-set-id] :as _args}]
|
[{:keys [x y position token token-type action selected-token-set-id] :as _args}]
|
||||||
(let [wrapper-style (use-viewport-position-style x y position (= token-type :color))
|
(let [wrapper-style (use-viewport-position-style x y position token-type)
|
||||||
modal-size-large* (mf/use-state (= token-type :typography))
|
modal-size-large* (mf/use-state (or (= token-type :typography)
|
||||||
|
(= token-type :color)
|
||||||
|
(= token-type :shadow)))
|
||||||
modal-size-large? (deref modal-size-large*)
|
modal-size-large? (deref modal-size-large*)
|
||||||
close-modal (mf/use-fn
|
close-modal (mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
|
|||||||
@ -1226,16 +1226,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@penpot/svgo@penpot/svgo#v3.1":
|
"@penpot/svgo@penpot/svgo#v3.2":
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
resolution: "@penpot/svgo@https://github.com/penpot/svgo.git#commit=a46262c12c0d967708395972c374eb2adead4180"
|
resolution: "@penpot/svgo@https://github.com/penpot/svgo.git#commit=8c9b0e32e9cb5f106085260bd9375f3c91a5010b"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@trysound/sax": "npm:0.2.0"
|
"@trysound/sax": "npm:0.2.0"
|
||||||
css-select: "npm:^5.1.0"
|
css-select: "npm:^5.1.0"
|
||||||
css-tree: "npm:^3.1.0"
|
css-tree: "npm:^3.1.0"
|
||||||
csso: "npm:^5.0.5"
|
csso: "npm:^5.0.5"
|
||||||
lodash: "npm:^4.17.21"
|
lodash: "npm:^4.17.21"
|
||||||
checksum: 10c0/db5f81c99dec2765721d73b69bb30594869ebf657380dfb46709c79775b6c0dc1af678fe9fe51bbe2272a2c78d19c2694a12ec6578bcc41235fa4aff475c9416
|
checksum: 10c0/d7af2801451b97f8ffb17664147c609456f5bcc786c6d03b222546125260c0f268e750748311d61598e31f66610b00038d2b969635b1a15e5694647e19c6b63a
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -4311,7 +4311,7 @@ __metadata:
|
|||||||
"@penpot/hljs": "portal:./vendor/hljs"
|
"@penpot/hljs": "portal:./vendor/hljs"
|
||||||
"@penpot/mousetrap": "portal:./vendor/mousetrap"
|
"@penpot/mousetrap": "portal:./vendor/mousetrap"
|
||||||
"@penpot/plugins-runtime": "npm:1.3.2"
|
"@penpot/plugins-runtime": "npm:1.3.2"
|
||||||
"@penpot/svgo": "penpot/svgo#v3.1"
|
"@penpot/svgo": "penpot/svgo#v3.2"
|
||||||
"@penpot/text-editor": "portal:./text-editor"
|
"@penpot/text-editor": "portal:./text-editor"
|
||||||
"@playwright/test": "npm:1.52.0"
|
"@playwright/test": "npm:1.52.0"
|
||||||
"@storybook/addon-docs": "npm:10.0.4"
|
"@storybook/addon-docs": "npm:10.0.4"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user