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

This commit is contained in:
Andrey Antukh 2026-04-09 09:13:02 +02:00
commit 5937a8b0fc
17 changed files with 341 additions and 477 deletions

View File

@ -57,6 +57,29 @@
- Fix hover on layers [Taiga #13799](https://tree.taiga.io/project/penpot/issue/13799) - Fix hover on layers [Taiga #13799](https://tree.taiga.io/project/penpot/issue/13799)
## 2.14.2
### :sparkles: New features & Enhancements
- Add protection for stale JS asset cache to force reload on version mismatch [Github #8638](https://github.com/penpot/penpot/pull/8638)
- Normalize newsletter opt-in checkbox across different register flows [Github #8839](https://github.com/penpot/penpot/pull/8839)
### :bug: Bugs fixed
- Fix PathData corruption root causes across WASM and CLJS (unsafe transmute and byteOffset handling)
- Handle corrupted PathData segments gracefully instead of crashing
- Fix swapped move-to/line-to type codes in PathData binary readers
- Fix non-integer row/column values in grid cell position inputs [Github #8869](https://github.com/penpot/penpot/pull/8869)
- Fix nil path content crash by exposing safe public API [Github #8806](https://github.com/penpot/penpot/pull/8806)
- Fix infinite recursion in get-frame-ids for thumbnail extraction [Github #8807](https://github.com/penpot/penpot/pull/8807)
- Fix stale-asset detector missing protocol-dispatch errors
- Ignore Zone.js toString TypeError in uncaught error handler [Github #8804](https://github.com/penpot/penpot/pull/8804)
- Prevent thumbnail frame recursion overflow [Github #8763](https://github.com/penpot/penpot/pull/8763)
- Fix vector index out of bounds in viewer zoom-to-fit/fill [Github #8834](https://github.com/penpot/penpot/pull/8834)
- Guard delete undo against missing sibling order [Github #8858](https://github.com/penpot/penpot/pull/8858)
- Fix ICounted error on numeric-input token dropdown keyboard nav [Github #8803](https://github.com/penpot/penpot/pull/8803)
## 2.14.1 ## 2.14.1
### :sparkles: New features & Enhancements ### :sparkles: New features & Enhancements

View File

@ -423,7 +423,7 @@
(defn- qualify-prop-key (defn- qualify-prop-key
[provider k] [provider k]
(keyword (:type provider) (name k))) (keyword (:type provider) (-> k name str/kebab)))
(defn- qualify-props (defn- qualify-props
[provider props] [provider props]

View File

@ -253,12 +253,15 @@
:hint "email has complaint reports"))) :hint "email has complaint reports")))
(defn prepare-register (defn prepare-register
[{:keys [::db/pool] :as cfg} {:keys [fullname email accept-newsletter-updates] :as params}] [{:keys [::db/pool] :as cfg} {:keys [fullname email] :as params}]
(validate-register-attempt! cfg params) (validate-register-attempt! cfg params)
(let [email (profile/clean-email email) (let [email (profile/clean-email email)
profile (profile/get-profile-by-email pool email) profile (profile/get-profile-by-email pool email)
props (-> (audit/extract-utm-params params)
(cond-> (:accept-newsletter-updates params)
(assoc :newsletter-updates true)))
params {:email email params {:email email
:fullname fullname :fullname fullname
:password (:password params) :password (:password params)
@ -267,13 +270,12 @@
:iss :prepared-register :iss :prepared-register
:profile-id (:id profile) :profile-id (:id profile)
:exp (ct/in-future {:days 7}) :exp (ct/in-future {:days 7})
:props {:newsletter-updates (or accept-newsletter-updates false)}} :props props}
params (d/without-nils params) params (d/without-nils params)
token (tokens/generate cfg params)] token (tokens/generate cfg params)]
(with-meta {:token token} (-> {:token token}
{::audit/profile-id uuid/zero}))) (with-meta {::audit/profile-id uuid/zero}))))
(def schema:prepare-register-profile (def schema:prepare-register-profile
[:map {:title "prepare-register-profile"} [:map {:title "prepare-register-profile"}
@ -281,6 +283,7 @@
[:email ::sm/email] [:email ::sm/email]
[:password schema:password] [:password schema:password]
[:create-welcome-file {:optional true} :boolean] [:create-welcome-file {:optional true} :boolean]
[:accept-newsletter-updates {:optional true} :boolean]
[:invitation-token {:optional true} schema:token]]) [:invitation-token {:optional true} schema:token]])
(sv/defmethod ::prepare-register-profile (sv/defmethod ::prepare-register-profile
@ -317,8 +320,7 @@
attrs (all the other attrs are filled with default values)." attrs (all the other attrs are filled with default values)."
[{:keys [::db/conn] :as cfg} {:keys [email] :as params}] [{:keys [::db/conn] :as cfg} {:keys [email] :as params}]
(let [id (or (:id params) (uuid/next)) (let [id (or (:id params) (uuid/next))
props (-> (audit/extract-utm-params params) props (-> (:props params)
(merge (:props params))
(merge {:viewed-tutorial? false (merge {:viewed-tutorial? false
:viewed-walkthrough? false :viewed-walkthrough? false
:nudge {:big 10 :small 1} :nudge {:big 10 :small 1}
@ -369,7 +371,6 @@
:cause cause) :cause cause)
(throw cause)))))) (throw cause))))))
(defn create-profile-rels (defn create-profile-rels
[{:keys [::db/conn] :as cfg} {:keys [id] :as profile}] [{:keys [::db/conn] :as cfg} {:keys [id] :as profile}]
(assert (db/connection-map? cfg) (assert (db/connection-map? cfg)
@ -411,7 +412,9 @@
(defn register-profile (defn register-profile
[{:keys [::db/conn ::wrk/executor] :as cfg} {:keys [token] :as params}] [{:keys [::db/conn ::wrk/executor] :as cfg} {:keys [token] :as params}]
(let [claims (tokens/verify cfg {:token token :iss :prepared-register}) (let [claims (tokens/verify cfg {:token token :iss :prepared-register})
params (into claims params) params (cond-> claims
(:accept-newsletter-updates params)
(update :props assoc :newsletter-updates true))
profile (if-let [profile-id (:profile-id claims)] profile (if-let [profile-id (:profile-id claims)]
(profile/get-profile conn profile-id) (profile/get-profile conn profile-id)
@ -526,7 +529,8 @@
(def schema:register-profile (def schema:register-profile
[:map {:title "register-profile"} [:map {:title "register-profile"}
[:token schema:token]]) [:token schema:token]
[:accept-newsletter-updates {:optional true} :boolean]])
(sv/defmethod ::register-profile (sv/defmethod ::register-profile
{::rpc/auth false {::rpc/auth false

View File

@ -380,7 +380,9 @@
(let [data {::th/type :prepare-register-profile (let [data {::th/type :prepare-register-profile
:email "user@example.com" :email "user@example.com"
:fullname "foobar" :fullname "foobar"
:password "foobar"} :password "foobar"
:utm_campaign "utma"
:mtm_campaign "mtma"}
out (th/command! data) out (th/command! data)
token (get-in out [:result :token])] token (get-in out [:result :token])]
(t/is (string? token)) (t/is (string? token))
@ -396,11 +398,9 @@
;; try correct register ;; try correct register
(let [data {::th/type :register-profile (let [data {::th/type :register-profile
:token token :token token}
:utm_campaign "utma" out (th/command! data)]
:mtm_campaign "mtma"}] (t/is (nil? (:error out))))
(let [{:keys [result error]} (th/command! data)]
(t/is (nil? error))))
(let [profile (some-> (th/db-get :profile {:email "user@example.com"}) (let [profile (some-> (th/db-get :profile {:email "user@example.com"})
(profile/decode-row))] (profile/decode-row))]

View File

@ -110,6 +110,18 @@ If you just want to try Penpot MCP quickly, follow this path for the **hosted (r
### Remote MCP in 5 steps ### Remote MCP in 5 steps
<div class="advice">
### Important: remote MCP is not in production yet
Remote MCP is not available yet in Penpot production (`design.penpot.app`). It is planned for an upcoming release (currently targeted around **2.16**).
Right now, the remote MCP flow is available only in **testing environments** (for example, instances deployed from the `staging` branch: https://github.com/penpot/penpot/tree/staging).
If you need MCP in production today, use the **Local MCP server** setup instead. See [Local MCP server](#local-mcp-server).
</div>
1. #### Enable MCP in Penpot 1. #### Enable MCP in Penpot
Go to **Your account → Integrations → MCP Server (Beta)** and enable the feature. Go to **Your account → Integrations → MCP Server (Beta)** and enable the feature.
@ -286,6 +298,16 @@ In Penpot, open a file and connect the plugin from **File → MCP Server → Con
Remote MCP is the easiest way to start using AI agents with Penpot. It's hosted for you, so you don't need to install or run anything on your machine. Remote MCP is the easiest way to start using AI agents with Penpot. It's hosted for you, so you don't need to install or run anything on your machine.
<div class="advice">
### Availability note
Remote MCP is currently available only in **testing environments**. It is not yet available in Penpot production (`design.penpot.app`) and is planned for an upcoming release (currently targeted around **2.16**).
If you need MCP in production today, use the **Local MCP server** setup instead. See [Local MCP server](#local-mcp-server).
</div>
<a id="install-and-activate-remote"></a> <a id="install-and-activate-remote"></a>
### Install and activate ### Install and activate

View File

@ -24,7 +24,6 @@
[app.main.ui.exports.files] [app.main.ui.exports.files]
[app.main.ui.frame-preview :as frame-preview] [app.main.ui.frame-preview :as frame-preview]
[app.main.ui.notifications :as notifications] [app.main.ui.notifications :as notifications]
[app.main.ui.onboarding.newsletter :refer [onboarding-newsletter]]
[app.main.ui.onboarding.questions :refer [questions-modal]] [app.main.ui.onboarding.questions :refer [questions-modal]]
[app.main.ui.onboarding.team-choice :refer [onboarding-team-modal]] [app.main.ui.onboarding.team-choice :refer [onboarding-team-modal]]
[app.main.ui.releases :refer [release-notes-modal]] [app.main.ui.releases :refer [release-notes-modal]]
@ -160,12 +159,6 @@
(not (:onboarding-viewed props)) (not (:onboarding-viewed props))
(not (contains? props :onboarding-questions))) (not (contains? props :onboarding-questions)))
show-newsletter-modal?
(and (contains? cf/flags :onboarding)
(not (:onboarding-viewed props))
(not (contains? props :newsletter-updates))
(contains? props :onboarding-questions))
show-team-modal? show-team-modal?
(and (contains? cf/flags :onboarding) (and (contains? cf/flags :onboarding)
(not (:onboarding-viewed props)) (not (:onboarding-viewed props))
@ -242,9 +235,6 @@
show-question-modal? show-question-modal?
[:& questions-modal] [:& questions-modal]
show-newsletter-modal?
[:& onboarding-newsletter]
show-team-modal? show-team-modal?
[:& onboarding-team-modal {:go-to-team true}] [:& onboarding-team-modal {:go-to-team true}]

View File

@ -13,7 +13,7 @@
[app.main.ui.auth.login :refer [login-page]] [app.main.ui.auth.login :refer [login-page]]
[app.main.ui.auth.recovery :refer [recovery-page]] [app.main.ui.auth.recovery :refer [recovery-page]]
[app.main.ui.auth.recovery-request :refer [recovery-request-page]] [app.main.ui.auth.recovery-request :refer [recovery-request-page]]
[app.main.ui.auth.register :refer [register-page register-success-page register-validate-page terms-register]] [app.main.ui.auth.register :refer [register-page* register-success-page* register-validate-page* terms-register*]]
[app.main.ui.icons :as deprecated-icon] [app.main.ui.icons :as deprecated-icon]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -21,14 +21,19 @@
(mf/defc auth* (mf/defc auth*
[{:keys [route]}] [{:keys [route]}]
(let [section (dm/get-in route [:data :name]) (let [section
is-register (or (dm/get-in route [:data :name])
(= section :auth-register)
(= section :auth-register-validate) is-register
(= section :register-validate-page) (or (= section :auth-register)
(= section :auth-register-success)) (= section :auth-register-validate)
params (:query-params route) (= section :register-validate-page)
error (:error params)] (= section :auth-register-success))
params
(:query-params route)
error
(:error params)]
(mf/with-effect [] (mf/with-effect []
(dom/set-html-title (tr "title.default"))) (dom/set-html-title (tr "title.default")))
@ -49,13 +54,13 @@
(case section (case section
:auth-register :auth-register
[:& register-page {:params params}] [:> register-page* {:params params}]
:auth-register-success :auth-register-success
[:& register-success-page {:params params}] [:> register-success-page* {:params params}]
:auth-register-validate :auth-register-validate
[:& register-validate-page {:params params}] [:> register-validate-page* {:params params}]
:auth-login :auth-login
[:& login-page {:params params}] [:& login-page {:params params}]
@ -67,7 +72,7 @@
[:& recovery-page {:params params}]) [:& recovery-page {:params params}])
(when (= section :auth-register) (when (= section :auth-register)
[:& terms-register])]])) [:> terms-register*])]]))
(mf/defc auth-page* (mf/defc auth-page*

View File

@ -20,7 +20,6 @@
[app.main.ui.components.link :as lk] [app.main.ui.components.link :as lk]
[app.main.ui.ds.notifications.context-notification :refer [context-notification*]] [app.main.ui.ds.notifications.context-notification :refer [context-notification*]]
[app.main.ui.icons :as deprecated-icon] [app.main.ui.icons :as deprecated-icon]
[app.main.ui.notifications.context-notification :refer [context-notification]]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :refer [tr]] [app.util.i18n :refer [tr]]
[app.util.storage :as s] [app.util.storage :as s]
@ -34,10 +33,9 @@
:login-with-gitlab :login-with-gitlab
:login-with-oidc])) :login-with-oidc]))
(mf/defc demo-warning (mf/defc demo-warning*
{::mf/props :obj}
[] []
[:& context-notification [:> context-notification*
{:level :warning {:level :warning
:content (tr "auth.demo-warning")}]) :content (tr "auth.demo-warning")}])
@ -275,7 +273,7 @@
(tr "auth.login-tagline")] (tr "auth.login-tagline")]
(when (contains? cf/flags :demo-warning) (when (contains? cf/flags :demo-warning)
[:& demo-warning]) [:> demo-warning*])
[:> login-dialog* {:params params}] [:> login-dialog* {:params params}]

View File

@ -40,9 +40,8 @@
:default-checked false :default-checked false
:label updates-label}]])) :label updates-label}]]))
(mf/defc terms-and-privacy (mf/defc terms-and-privacy*
{::mf/props :obj {::mf/private true}
::mf/private true}
[] []
(let [terms-label (let [terms-label
(mf/html (mf/html
@ -70,8 +69,7 @@
[:accept-newsletter-updates {:optional true} :boolean] [:accept-newsletter-updates {:optional true} :boolean]
[:token {:optional true} ::sm/text]]) [:token {:optional true} ::sm/text]])
(mf/defc register-form (mf/defc register-form*
{::mf/props :obj}
[{:keys [params on-success-callback]}] [{:keys [params on-success-callback]}]
(let [initial (mf/use-memo (mf/deps params) (constantly params)) (let [initial (mf/use-memo (mf/deps params) (constantly params))
form (fm/use-form :schema schema:register-form form (fm/use-form :schema schema:register-form
@ -150,8 +148,7 @@
(assoc :create-welcome-file true))] (assoc :create-welcome-file true))]
(->> (rp/cmd! :prepare-register-profile cdata) (->> (rp/cmd! :prepare-register-profile cdata)
(rx/finalize #(reset! submitted? false)) (rx/subs! on-register-profile on-error #(reset! submitted? false))))))]
(rx/subs! on-register-profile on-error)))))]
[:& fm/form {:on-submit on-submit :form form} [:& fm/form {:on-submit on-submit :form form}
[:div {:class (stl/css :fields-row)} [:div {:class (stl/css :fields-row)}
@ -177,7 +174,7 @@
:class (stl/css :form-field)}]] :class (stl/css :form-field)}]]
(when (contains? cf/flags :terms-and-privacy-checkbox) (when (contains? cf/flags :terms-and-privacy-checkbox)
[:& terms-and-privacy]) [:> terms-and-privacy*])
[:> newsletter-options*] [:> newsletter-options*]
@ -187,8 +184,7 @@
:data-testid "register-form-submit" :data-testid "register-form-submit"
:class (stl/css :register-btn)}]])) :class (stl/css :register-btn)}]]))
(mf/defc register-methods (mf/defc register-methods*
{::mf/props :obj}
[{:keys [params hide-separator on-success-callback]}] [{:keys [params hide-separator on-success-callback]}]
[:* [:*
(when login/show-sso-login-buttons? (when login/show-sso-login-buttons?
@ -196,19 +192,18 @@
(when (or login/show-sso-login-buttons? (false? hide-separator)) (when (or login/show-sso-login-buttons? (false? hide-separator))
[:hr {:class (stl/css :separator)}]) [:hr {:class (stl/css :separator)}])
(when (contains? cf/flags :login-with-password) (when (contains? cf/flags :login-with-password)
[:& register-form {:params params :on-success-callback on-success-callback}])]) [:> register-form* {:params params :on-success-callback on-success-callback}])])
(mf/defc register-page (mf/defc register-page*
{::mf/props :obj}
[{:keys [params]}] [{:keys [params]}]
[:div {:class (stl/css :auth-form-wrapper :register-form)} [:div {:class (stl/css :auth-form-wrapper :register-form)}
[:h1 {:class (stl/css :auth-title) [:h1 {:class (stl/css :auth-title)
:data-testid "registration-title"} (tr "auth.register-title")] :data-testid "registration-title"} (tr "auth.register-title")]
(when (contains? cf/flags :demo-warning) (when (contains? cf/flags :demo-warning)
[:& login/demo-warning]) [:> login/demo-warning*])
[:& register-methods {:params params}] [:> register-methods* {:params params}]
[:div {:class (stl/css :links)} [:div {:class (stl/css :links)}
[:div {:class (stl/css :account)} [:div {:class (stl/css :account)}
@ -228,8 +223,7 @@
;; --- PAGE: register success page ;; --- PAGE: register success page
(mf/defc register-success-page (mf/defc register-success-page*
{::mf/props :obj}
[{:keys [params]}] [{:keys [params]}]
(let [email (or (:email params) (::email storage/user))] (let [email (or (:email params) (::email storage/user))]
[:div {:class (stl/css :auth-form-wrapper :register-success)} [:div {:class (stl/css :auth-form-wrapper :register-success)}
@ -239,8 +233,7 @@
[:div {:class (stl/css :notification-text)} (tr "auth.verification-email-sent")]] [:div {:class (stl/css :notification-text)} (tr "auth.verification-email-sent")]]
[:div {:class (stl/css :notification-text-email)} email]])) [:div {:class (stl/css :notification-text-email)} email]]))
(mf/defc terms-register*
(mf/defc terms-register
[] []
(let [show-all? (and cf/terms-of-service-uri cf/privacy-policy-uri) (let [show-all? (and cf/terms-of-service-uri cf/privacy-policy-uri)
show-terms? (some? cf/terms-of-service-uri) show-terms? (some? cf/terms-of-service-uri)
@ -267,13 +260,14 @@
[:token ::sm/text] [:token ::sm/text]
[:fullname [::sm/text {:max 250}]] [:fullname [::sm/text {:max 250}]]
[:accept-terms-and-privacy {:optional (not (contains? cf/flags :terms-and-privacy-checkbox))} [:accept-terms-and-privacy {:optional (not (contains? cf/flags :terms-and-privacy-checkbox))}
[:and :boolean [:= true]]]]) [:and :boolean [:= true]]]
[:accept-newsletter-updates {:optional true} :boolean]])
(mf/defc register-validate-form (mf/defc register-validate-form*
{::mf/props :obj {::mf/private true}
::mf/private true}
[{:keys [params on-success-callback]}] [{:keys [params on-success-callback]}]
(let [form (fm/use-form :schema schema:register-validate-form :initial params) (let [form
(fm/use-form :schema schema:register-validate-form :initial params)
submitted? submitted?
(mf/use-state false) (mf/use-state false)
@ -331,7 +325,9 @@
:class (stl/css :form-field)}]] :class (stl/css :form-field)}]]
(when (contains? cf/flags :terms-and-privacy-checkbox) (when (contains? cf/flags :terms-and-privacy-checkbox)
[:& terms-and-privacy]) [:> terms-and-privacy*])
[:> newsletter-options*]
[:> fm/submit-button* [:> fm/submit-button*
{:label (tr "auth.register-submit") {:label (tr "auth.register-submit")
@ -339,8 +335,7 @@
:class (stl/css :register-btn)}]])) :class (stl/css :register-btn)}]]))
(mf/defc register-validate-page (mf/defc register-validate-page*
{::mf/props :obj}
[{:keys [params]}] [{:keys [params]}]
[:div {:class (stl/css :auth-form-wrapper :register-form)} [:div {:class (stl/css :auth-form-wrapper :register-form)}
@ -350,7 +345,7 @@
:data-testid "register-title"} (tr "auth.register-account-title")] :data-testid "register-title"} (tr "auth.register-account-title")]
[:div {:class (stl/css :auth-subtitle)} (tr "auth.register-account-tagline")]] [:div {:class (stl/css :auth-subtitle)} (tr "auth.register-account-tagline")]]
[:& register-validate-form {:params params}] [:> register-validate-form* {:params params}]
[:div {:class (stl/css :links)} [:div {:class (stl/css :links)}
[:div {:class (stl/css :go-back)} [:div {:class (stl/css :go-back)}

View File

@ -44,6 +44,7 @@
step-value (d/parse-double step-value 1) step-value (d/parse-double step-value 1)
default (d/parse-double default (when-not nillable? 0)) default (d/parse-double default (when-not nillable? 0))
integer? (unchecked-get props "integer")
select-on-focus? (d/nilv (unchecked-get props "selectOnFocus") true) select-on-focus? (d/nilv (unchecked-get props "selectOnFocus") true)
;; We need a ref pointing to the input dom element, but the user ;; We need a ref pointing to the input dom element, but the user
@ -69,7 +70,7 @@
parse-value parse-value
(mf/use-fn (mf/use-fn
(mf/deps min-value max-value value nillable? default) (mf/deps min-value max-value value nillable? default integer?)
(fn [] (fn []
(when-let [node (mf/ref-val ref)] (when-let [node (mf/ref-val ref)]
(let [new-value (-> (dom/get-value node) (let [new-value (-> (dom/get-value node)
@ -78,6 +79,7 @@
(cond (cond
(d/num? new-value) (d/num? new-value)
(-> new-value (-> new-value
(cond-> integer? mth/round)
(d/max (/ sm/min-safe-int 2)) (d/max (/ sm/min-safe-int 2))
(d/min (/ sm/max-safe-int 2)) (d/min (/ sm/max-safe-int 2))
(cond-> (d/num? min-value) (cond-> (d/num? min-value)
@ -152,7 +154,8 @@
(and (d/num? max-value) (> new-value max-value)) (and (d/num? max-value) (> new-value max-value))
max-value max-value
:else new-value)] :else new-value)
new-value (if integer? (mth/round new-value) new-value)]
(apply-value event new-value)))))) (apply-value event new-value))))))
@ -297,6 +300,7 @@
props (-> (obj/clone props) props (-> (obj/clone props)
(obj/unset! "selectOnFocus") (obj/unset! "selectOnFocus")
(obj/unset! "nillable") (obj/unset! "nillable")
(obj/unset! "integer")
(obj/set! "value" mf/undefined) (obj/set! "value" mf/undefined)
(obj/set! "onChange" handle-change) (obj/set! "onChange" handle-change)
(obj/set! "className" class) (obj/set! "className" class)

View File

@ -1,105 +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.onboarding.newsletter
(:require-macros [app.main.style :as stl])
(:require
[app.main.data.event :as-alias ev]
[app.main.data.notifications :as ntf]
[app.main.data.profile :as du]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.icons :as deprecated-icon]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[potok.v2.core :as ptk]
[rumext.v2 :as mf]))
(mf/defc onboarding-newsletter
[]
(let [state* (mf/use-state #(do {:newsletter-updates false
:newsletter-news false}))
state (deref state*)
team (mf/deref refs/team)
on-change
(mf/use-fn
(fn [event]
(let [attr (-> (dom/get-current-target event)
(dom/get-data "attr")
(keyword))]
(swap! state* update attr not))))
on-next
(mf/use-fn
(mf/deps state team)
(fn []
(when (or (:newsletter-updates state)
(:newsletter-news state))
(st/emit! (ntf/success (tr "onboarding.newsletter.acceptance-message"))))
(let [params (-> state
(assoc ::ev/name "onboarding-step")
(assoc :label "newsletter:subscriptions")
(assoc :step 6))]
(st/emit! (ptk/data-event ::ev/event params)
(du/update-profile-props
(cond-> state
(not (:is-default team))
(assoc :onboarding-viewed true)))))))]
[:div {:class (stl/css-case
:modal-overlay true)}
[:div.animated.fadeInDown {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-left)}
[:img {:src "images/newsletter-notification.svg"}]]
[:div {:class (stl/css :modal-right)}
[:h2 {:class (stl/css :modal-title)
:data-testid "onboarding-newsletter-title"}
(tr "onboarding.newsletter.title")]
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.newsletter.desc")]
[:div {:class (stl/css :newsletter-options)}
[:div {:class (stl/css :input-wrapper)}
[:label {:for "newsletter-updates"}
[:span {:class (stl/css-case :global/checked (:newsletter-updates state))}
deprecated-icon/status-tick]
(tr "onboarding-v2.newsletter.updates")
[:input {:type "checkbox"
:id "newsletter-updates"
:data-attr "newsletter-updates"
:value (:newsletter-updates state)
:on-change on-change}]]]
[:div {:class (stl/css :input-wrapper)}
[:label {:for "newsletter-news"}
[:span {:class (stl/css-case :global/checked (:newsletter-news state))}
deprecated-icon/status-tick]
(tr "onboarding-v2.newsletter.news")
[:input {:type "checkbox"
:id "newsletter-news"
:data-attr "newsletter-news"
:value (:newsletter-news state)
:on-change on-change}]]]]
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.newsletter.privacy1")
[:a {:class (stl/css :modal-link)
:target "_blank"
:href "https://penpot.app/privacy"}
(tr "onboarding.newsletter.policy")]]
[:p {:class (stl/css :modal-text)}
(tr "onboarding-v2.newsletter.privacy2")]
[:button {:on-click on-next
:class (stl/css :accept-btn)}
(tr "labels.continue")]]]]))

View File

@ -1,82 +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;
.modal-overlay {
@extend %modal-overlay-base;
}
.modal-container {
@extend %modal-container-base;
position: relative;
display: grid;
grid-template-columns: auto auto;
gap: deprecated.$s-32;
padding-inline: deprecated.$s-100;
padding-block: deprecated.$s-100 deprecated.$s-72;
margin: 0;
width: deprecated.$s-960;
height: deprecated.$s-632;
max-width: deprecated.$s-960;
max-height: deprecated.$s-632;
}
.modal-left {
width: deprecated.$s-172;
margin-block-end: deprecated.$s-64;
img {
width: deprecated.$s-172;
border-radius: deprecated.$br-8 0 0 deprecated.$br-8;
height: auto;
}
}
.modal-right {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: deprecated.$s-40 auto auto auto auto deprecated.$s-32;
gap: deprecated.$s-24;
position: relative;
}
.modal-title {
@include deprecated.bigTitleTipography;
color: var(--modal-title-foreground-color);
}
.modal-text {
@include deprecated.bodyLargeTypography;
color: var(--modal-text-foreground-color);
margin: 0;
}
.newsletter-options {
display: grid;
gap: deprecated.$s-16;
margin-inline-start: deprecated.$s-16;
}
.input-wrapper {
@extend %input-checkbox;
}
.modal-link {
@include deprecated.bodyLargeTypography;
color: var(--modal-link-foreground-color);
margin: 0;
}
.accept-btn {
@extend %modal-accept-btn;
justify-self: flex-end;
}

View File

@ -150,7 +150,7 @@
[:* [:*
[:div {:class (stl/css :logo-title)} (tr "not-found.login.signup-free")] [:div {:class (stl/css :logo-title)} (tr "not-found.login.signup-free")]
[:div {:class (stl/css :logo-subtitle)} (tr "not-found.login.start-using")] [:div {:class (stl/css :logo-subtitle)} (tr "not-found.login.start-using")]
[:& register/register-methods {:on-success-callback success-register :hide-separator true}] [:> register/register-methods* {:on-success-callback success-register :hide-separator true}]
#_[:hr {:class (stl/css :separator)}] #_[:hr {:class (stl/css :separator)}]
[:div {:class (stl/css :separator)}] [:div {:class (stl/css :separator)}]
[:div {:class (stl/css :change-section)} [:div {:class (stl/css :change-section)}
@ -160,11 +160,11 @@
:on-click set-section} (tr "auth.login-here")]] :on-click set-section} (tr "auth.login-here")]]
[:div {:class (stl/css :links)} [:div {:class (stl/css :links)}
[:hr {:class (stl/css :separator)}] [:hr {:class (stl/css :separator)}]
[:& register/terms-register]]] [:> register/terms-register*]]]
:register-validate :register-validate
[:div {:class (stl/css :form-container)} [:div {:class (stl/css :form-container)}
[:& register/register-form [:> register/register-form*
{:params {:token @register-token} {:params {:token @register-token}
:on-success-callback register-email-sent}] :on-success-callback register-email-sent}]
[:div {:class (stl/css :links)} [:div {:class (stl/css :links)}
@ -175,7 +175,7 @@
:register-email-sent :register-email-sent
[:div {:class (stl/css :form-container)} [:div {:class (stl/css :form-container)}
[:& register/register-success-page {:params {:email @user-email :hide-logo true}}]] [:> register/register-success-page* {:params {:email @user-email :hide-logo true}}]]
:recovery-request :recovery-request
[:& recovery-request-page {:go-back-callback set-section-login [:& recovery-request-page {:go-back-callback set-section-login

View File

@ -12,7 +12,7 @@
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.auth.login :refer [login-dialog*]] [app.main.ui.auth.login :refer [login-dialog*]]
[app.main.ui.auth.recovery-request :refer [recovery-request-page]] [app.main.ui.auth.recovery-request :refer [recovery-request-page]]
[app.main.ui.auth.register :refer [register-methods register-success-page terms-register register-validate-form]] [app.main.ui.auth.register :refer [register-methods* register-success-page* terms-register* register-validate-form*]]
[app.main.ui.icons :as deprecated-icon] [app.main.ui.icons :as deprecated-icon]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -94,7 +94,7 @@
:register :register
[:div {:class (stl/css :form-container)} [:div {:class (stl/css :form-container)}
[:& register-methods {:on-success-callback success-register}] [:> register-methods* {:on-success-callback success-register}]
[:div {:class (stl/css :links)} [:div {:class (stl/css :links)}
[:div {:class (stl/css :account)} [:div {:class (stl/css :account)}
[:span (tr "auth.already-have-account") " "] [:span (tr "auth.already-have-account") " "]
@ -104,8 +104,8 @@
:register-validate :register-validate
[:div {:class (stl/css :form-container)} [:div {:class (stl/css :form-container)}
[:& register-validate-form {:params {:token @register-token} [:> register-validate-form* {:params {:token @register-token}
:on-success-callback success-email-sent}] :on-success-callback success-email-sent}]
[:div {:class (stl/css :links)} [:div {:class (stl/css :links)}
[:div {:class (stl/css :register)} [:div {:class (stl/css :register)}
[:a {:on-click set-section [:a {:on-click set-section
@ -117,8 +117,8 @@
:on-success-callback success-email-sent}] :on-success-callback success-email-sent}]
:email-sent :email-sent
[:div {:class (stl/css :form-container)} [:div {:class (stl/css :form-container)}
[:& register-success-page {:params {:email @user-email}}]]) [:> register-success-page* {:params {:email @user-email}}]])
(when main-section (when main-section
[:div {:class (stl/css :links)} [:div {:class (stl/css :links)}
[:& terms-register]])]]])) [:> terms-register*]])]]]))

View File

@ -10,6 +10,7 @@
[app.common.attrs :as attrs] [app.common.attrs :as attrs]
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.math :as mth]
[app.common.types.shape.layout :as ctl] [app.common.types.shape.layout :as ctl]
[app.main.data.workspace :as dw] [app.main.data.workspace :as dw]
[app.main.data.workspace.grid-layout.editor :as dwge] [app.main.data.workspace.grid-layout.editor :as dwge]
@ -133,7 +134,10 @@
(mf/deps column row (:id shape) (:id cell)) (mf/deps column row (:id shape) (:id cell))
(fn [field type value] (fn [field type value]
(when-not multiple? (when-not multiple?
(let [[property value] (let [value (mth/round value)
column (mth/round column)
row (mth/round row)
[property value]
(cond (cond
(and (= type :column) (or (= field :all) (= field :start))) (and (= type :column) (or (= field :all) (= field :start)))
[:column value] [:column value]
@ -216,6 +220,7 @@
:title "Column" :title "Column"
:on-click #(dom/select-target %) :on-click #(dom/select-target %)
:on-change (partial on-grid-coordinates :all :column) :on-change (partial on-grid-coordinates :all :column)
:integer true
:value column}]]] :value column}]]]
[:div {:class (stl/css :grid-coord-group)} [:div {:class (stl/css :grid-coord-group)}
@ -226,6 +231,7 @@
:title "Row" :title "Row"
:on-click #(dom/select-target %) :on-click #(dom/select-target %)
:on-change (partial on-grid-coordinates :all :row) :on-change (partial on-grid-coordinates :all :row)
:integer true
:value row}]]]]) :value row}]]]])
(when (and (not multiple?) (or (= :manual cell-mode) (= :area cell-mode))) (when (and (not multiple?) (or (= :manual cell-mode) (= :area cell-mode)))
@ -237,12 +243,14 @@
{:placeholder "--" {:placeholder "--"
:on-pointer-down #(dom/select-target %) :on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :start :column) :on-change (partial on-grid-coordinates :start :column)
:integer true
:value column}]] :value column}]]
[:div {:class (stl/css :coord-input)} [:div {:class (stl/css :coord-input)}
[:> numeric-input* [:> numeric-input*
{:placeholder "--" {:placeholder "--"
:on-pointer-down #(dom/select-target %) :on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :end :column) :on-change (partial on-grid-coordinates :end :column)
:integer true
:value column-end}]]] :value column-end}]]]
[:div {:class (stl/css :grid-coord-group)} [:div {:class (stl/css :grid-coord-group)}
@ -252,12 +260,14 @@
{:placeholder "--" {:placeholder "--"
:on-pointer-down #(dom/select-target %) :on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :start :row) :on-change (partial on-grid-coordinates :start :row)
:integer true
:value row}]] :value row}]]
[:div {:class (stl/css :coord-input)} [:div {:class (stl/css :coord-input)}
[:> numeric-input* [:> numeric-input*
{:placeholder "--" {:placeholder "--"
:on-pointer-down #(dom/select-target %) :on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :end :row) :on-change (partial on-grid-coordinates :end :row)
:integer true
:value row-end}]]]]) :value row-end}]]]])
[:div {:class (stl/css :row)} [:div {:class (stl/css :row)}

View File

@ -16,9 +16,9 @@
"fmt": "./scripts/fmt" "fmt": "./scripts/fmt"
}, },
"devDependencies": { "devDependencies": {
"@github/copilot": "^1.0.12", "@github/copilot": "^1.0.21",
"@types/node": "^20.12.7", "@types/node": "^25.5.2",
"esbuild": "^0.27.4", "esbuild": "^0.28.0",
"opencode-ai": "^1.3.17" "opencode-ai": "^1.4.0"
} }
} }

400
pnpm-lock.yaml generated
View File

@ -9,480 +9,480 @@ importers:
.: .:
devDependencies: devDependencies:
'@github/copilot': '@github/copilot':
specifier: ^1.0.12 specifier: ^1.0.21
version: 1.0.12 version: 1.0.21
'@types/node': '@types/node':
specifier: ^20.12.7 specifier: ^25.5.2
version: 20.19.37 version: 25.5.2
esbuild: esbuild:
specifier: ^0.27.4 specifier: ^0.28.0
version: 0.27.4 version: 0.28.0
opencode-ai: opencode-ai:
specifier: ^1.3.17 specifier: ^1.4.0
version: 1.3.17 version: 1.4.0
packages: packages:
'@esbuild/aix-ppc64@0.27.4': '@esbuild/aix-ppc64@0.28.0':
resolution: {integrity: sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==} resolution: {integrity: sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [ppc64] cpu: [ppc64]
os: [aix] os: [aix]
'@esbuild/android-arm64@0.27.4': '@esbuild/android-arm64@0.28.0':
resolution: {integrity: sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==} resolution: {integrity: sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@esbuild/android-arm@0.27.4': '@esbuild/android-arm@0.28.0':
resolution: {integrity: sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==} resolution: {integrity: sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm] cpu: [arm]
os: [android] os: [android]
'@esbuild/android-x64@0.27.4': '@esbuild/android-x64@0.28.0':
resolution: {integrity: sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==} resolution: {integrity: sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [android] os: [android]
'@esbuild/darwin-arm64@0.27.4': '@esbuild/darwin-arm64@0.28.0':
resolution: {integrity: sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==} resolution: {integrity: sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@esbuild/darwin-x64@0.27.4': '@esbuild/darwin-x64@0.28.0':
resolution: {integrity: sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==} resolution: {integrity: sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@esbuild/freebsd-arm64@0.27.4': '@esbuild/freebsd-arm64@0.28.0':
resolution: {integrity: sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==} resolution: {integrity: sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [freebsd] os: [freebsd]
'@esbuild/freebsd-x64@0.27.4': '@esbuild/freebsd-x64@0.28.0':
resolution: {integrity: sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==} resolution: {integrity: sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
'@esbuild/linux-arm64@0.27.4': '@esbuild/linux-arm64@0.28.0':
resolution: {integrity: sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==} resolution: {integrity: sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@esbuild/linux-arm@0.27.4': '@esbuild/linux-arm@0.28.0':
resolution: {integrity: sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==} resolution: {integrity: sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@esbuild/linux-ia32@0.27.4': '@esbuild/linux-ia32@0.28.0':
resolution: {integrity: sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==} resolution: {integrity: sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [ia32] cpu: [ia32]
os: [linux] os: [linux]
'@esbuild/linux-loong64@0.27.4': '@esbuild/linux-loong64@0.28.0':
resolution: {integrity: sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==} resolution: {integrity: sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [loong64] cpu: [loong64]
os: [linux] os: [linux]
'@esbuild/linux-mips64el@0.27.4': '@esbuild/linux-mips64el@0.28.0':
resolution: {integrity: sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==} resolution: {integrity: sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [mips64el] cpu: [mips64el]
os: [linux] os: [linux]
'@esbuild/linux-ppc64@0.27.4': '@esbuild/linux-ppc64@0.28.0':
resolution: {integrity: sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==} resolution: {integrity: sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [ppc64] cpu: [ppc64]
os: [linux] os: [linux]
'@esbuild/linux-riscv64@0.27.4': '@esbuild/linux-riscv64@0.28.0':
resolution: {integrity: sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==} resolution: {integrity: sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
'@esbuild/linux-s390x@0.27.4': '@esbuild/linux-s390x@0.28.0':
resolution: {integrity: sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==} resolution: {integrity: sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [s390x] cpu: [s390x]
os: [linux] os: [linux]
'@esbuild/linux-x64@0.27.4': '@esbuild/linux-x64@0.28.0':
resolution: {integrity: sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==} resolution: {integrity: sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@esbuild/netbsd-arm64@0.27.4': '@esbuild/netbsd-arm64@0.28.0':
resolution: {integrity: sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==} resolution: {integrity: sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [netbsd] os: [netbsd]
'@esbuild/netbsd-x64@0.27.4': '@esbuild/netbsd-x64@0.28.0':
resolution: {integrity: sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==} resolution: {integrity: sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [netbsd] os: [netbsd]
'@esbuild/openbsd-arm64@0.27.4': '@esbuild/openbsd-arm64@0.28.0':
resolution: {integrity: sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==} resolution: {integrity: sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [openbsd] os: [openbsd]
'@esbuild/openbsd-x64@0.27.4': '@esbuild/openbsd-x64@0.28.0':
resolution: {integrity: sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==} resolution: {integrity: sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [openbsd] os: [openbsd]
'@esbuild/openharmony-arm64@0.27.4': '@esbuild/openharmony-arm64@0.28.0':
resolution: {integrity: sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==} resolution: {integrity: sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [openharmony] os: [openharmony]
'@esbuild/sunos-x64@0.27.4': '@esbuild/sunos-x64@0.28.0':
resolution: {integrity: sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==} resolution: {integrity: sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [sunos] os: [sunos]
'@esbuild/win32-arm64@0.27.4': '@esbuild/win32-arm64@0.28.0':
resolution: {integrity: sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==} resolution: {integrity: sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@esbuild/win32-ia32@0.27.4': '@esbuild/win32-ia32@0.28.0':
resolution: {integrity: sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==} resolution: {integrity: sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [ia32] cpu: [ia32]
os: [win32] os: [win32]
'@esbuild/win32-x64@0.27.4': '@esbuild/win32-x64@0.28.0':
resolution: {integrity: sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==} resolution: {integrity: sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@github/copilot-darwin-arm64@1.0.12': '@github/copilot-darwin-arm64@1.0.21':
resolution: {integrity: sha512-fjbwRIUZAH06Eyg5ZkfZXg8SVXpqI3HaFhtXZ803CZs9mfIgfOSR3URZxUnv7SIv6aI/7f6ws8RxKnPGavJ/tg==} resolution: {integrity: sha512-aB+s9ldTwcyCOYmzjcQ4SknV6g81z92T8aUJEJZBwOXOTBeWKAJtk16ooAKangZgdwuLgO3or1JUjx1FJAm5nQ==}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
hasBin: true hasBin: true
'@github/copilot-darwin-x64@1.0.12': '@github/copilot-darwin-x64@1.0.21':
resolution: {integrity: sha512-/tJGJEEm8kpTW/sJRNnvhMSHKIHApNun14biuIkC5CXDqVgFakbKlckn/FlIkT48eEUysc0YbEatrHIDz/8XbA==} resolution: {integrity: sha512-aNad81DOGuGShmaiFNIxBUSZLwte0dXmDYkGfAF9WJIgY4qP4A8CPWFoNr8//gY+4CwaIf9V+f/OC6k2BdECbw==}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
hasBin: true hasBin: true
'@github/copilot-linux-arm64@1.0.12': '@github/copilot-linux-arm64@1.0.21':
resolution: {integrity: sha512-4977LVJi3/9Yc+ivj+VKDVtHg0kT5yqOrN8F35/jgqerx4Mdtk1pOMlWztXxLicBHN4y2V7/EY/wc0WqFW0Zvg==} resolution: {integrity: sha512-FL0NsCnHax4czHVv1S8iBqPLGZDhZ28N3+6nT29xWGhmjBWTkIofxLThKUPcyyMsfPTTxIlrdwWa8qQc5z2Q+g==}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
hasBin: true hasBin: true
'@github/copilot-linux-x64@1.0.12': '@github/copilot-linux-x64@1.0.21':
resolution: {integrity: sha512-9QevJZD29PVltYDV4xHWbdN6ud/966clERL5Frh2+9D3+spaVDO1hFllzoFiEwD/M4f2GkSh7/fT3hV0LKl9Ag==} resolution: {integrity: sha512-S7pWVI16hesZtxYbIyfw+MHZpc5ESoGKUVr5Y+lZJNaM2340gJGPQzQwSpvKIRMLHRKI2hXLwciAnYeMFxE/Tg==}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
hasBin: true hasBin: true
'@github/copilot-win32-arm64@1.0.12': '@github/copilot-win32-arm64@1.0.21':
resolution: {integrity: sha512-RLAbAsLniI8vA2utgZdIsvD8slZpz1fb8l6cmIiQvDE/BwQb2zNV9VepZ+CwzYtNx9ifxBtgIwYwUJq5bxeSaQ==} resolution: {integrity: sha512-a9qc2Ku+XbyBkXCclbIvBbIVnECACTIWnPctmXWsQeSdeapGxgfHGux7y8hAFV5j6+nhCm6cnyEMS3rkZjAhdA==}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
hasBin: true hasBin: true
'@github/copilot-win32-x64@1.0.12': '@github/copilot-win32-x64@1.0.21':
resolution: {integrity: sha512-4SYV09F4Sw20DAib1do26+ALZmCZrghzo+5e6IZbQOsm4B7NhBFaLpKFU+kEijfmWacLlh/at5CpGGGKlwlbcg==} resolution: {integrity: sha512-9klu+7NQ6tEyb8sibb0rsbimBivDrnNltZho10Bgbf1wh3o+erTjffXDjW9Zkyaw8lZA9Fz8bqhVkKntZq58Lg==}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
hasBin: true hasBin: true
'@github/copilot@1.0.12': '@github/copilot@1.0.21':
resolution: {integrity: sha512-GpmoJbs1ECyLLKtY4PcFzO8Cz6GgDTOKkrzwNdkirNdfsB+o6x0OOlFyrOdNXNPII7pk9+GcpIjF87sLwWzpPQ==} resolution: {integrity: sha512-P+nORjNKAtl92jYCG6Qr1Rsw2JoyScgeQSkIR6O2WB37WS5JVdA4ax1WVualMbfuc9V58CPHX6fwyNpkI89FkQ==}
hasBin: true hasBin: true
'@types/node@20.19.37': '@types/node@25.5.2':
resolution: {integrity: sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==} resolution: {integrity: sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==}
esbuild@0.27.4: esbuild@0.28.0:
resolution: {integrity: sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==} resolution: {integrity: sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==}
engines: {node: '>=18'} engines: {node: '>=18'}
hasBin: true hasBin: true
opencode-ai@1.3.17: opencode-ai@1.4.0:
resolution: {integrity: sha512-2Awq2za4kLPG9wxFHFmqcmoveTSTeyq7Q3GJ8PoQahjWU17yCjuyJUclouFULzaZgqA8atHOyT/3eUHigMc8Cw==} resolution: {integrity: sha512-Cb5Vo5Rl1gvOIXC8gtgupwoa5+rufsp+6u5tIxIYLl5fReX+P2eugLSOkKH2KB5GC6BwxaEvapEZiPvQYsZSXA==}
hasBin: true hasBin: true
opencode-darwin-arm64@1.3.17: opencode-darwin-arm64@1.4.0:
resolution: {integrity: sha512-aaMXeNQRPLdGPoxULFty1kxYxT2qPXCiqftYbLF2SQN9Xjq8BR3BjA766ncae1hdiDJJAe1CSpWDbobn5K+oyA==} resolution: {integrity: sha512-rXdrH1Oejb+220ZCzkd1P+tCP7IhLTyfRbUr89vzvEWVRueh0vr2hvyrGDVv9LAskZAt/hwY3Wnw9CzjtxocdQ==}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
opencode-darwin-x64-baseline@1.3.17: opencode-darwin-x64-baseline@1.4.0:
resolution: {integrity: sha512-ftEiCwzl6OjIqpXD075lHWHT1YKJjNDPvL1XlLDv86Wt4Noc818fl1lOWwg/LkNL04LoXD2oa3NGOJZYzd6STQ==} resolution: {integrity: sha512-5xCXF8Xn9M2WQKZATc4llm9qrAc4JodmQj88Oibbz/rXIOr/A1ejXvaeqLOQkQyQweeEABlYXOf3eCiY5hx8Gw==}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
opencode-darwin-x64@1.3.17: opencode-darwin-x64@1.4.0:
resolution: {integrity: sha512-fMlnOCtaMnwimdP81a3F7QK9GUwhrQnxaKuUZk31wYcGBGQKgSSdy2xK8CRLcaHEV8gLxSlcGJj7g4NTOrC9Tw==} resolution: {integrity: sha512-PhBfT2EtPos7jcGBtVSz3+yKv2e1nQy1UrXiH4ILdSgwzroKU/0kMsRtWJeMPHIj1imUQmSVlnDcuxiCiCkozw==}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
opencode-linux-arm64-musl@1.3.17: opencode-linux-arm64-musl@1.4.0:
resolution: {integrity: sha512-clD6K35+pP60xLiqCJFTTTpDK2XFahOlSo8TQckXCvCnYYwMqdK9sOO7uzDHLNyPIGLKiYNZTxqVazuGnbGmYQ==} resolution: {integrity: sha512-1lc0Nj6OmtJF5NJn+AhV7rXOHzw+0p7rvXQu2iqd9V7DpUEbltyF6oiyuF54gBZjHpvSzFXu8a3YeTcuMEXdNA==}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
opencode-linux-arm64@1.3.17: opencode-linux-arm64@1.4.0:
resolution: {integrity: sha512-gd4kndxNwYi9kINyrTItY35M7UZ4jAXMxbbdbFnUBFYI009uv4bgNofnZnVOAFfjc0/PpxSgdNn9eHDjlJEdJQ==} resolution: {integrity: sha512-XEM3tP7DTrYDEYCe9jqC/xtgzPJpCZTfinc5DjcPuh2hx+iHCGSr9+qG7tRGeCyvD9ibAFewNtpco5Is49JCrg==}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
opencode-linux-x64-baseline-musl@1.3.17: opencode-linux-x64-baseline-musl@1.4.0:
resolution: {integrity: sha512-BiNu5B6QfohG+KwNcY3YlKR465DNke0nknRqn3Ke2APp6GghuimlnyEKcji1brhZsdjdembc79KWfQcsHlYsyA==} resolution: {integrity: sha512-URg1JXIUaNz0R4TLUT98rK2jozmh5ScAkkqxPK6LWj3XwJojJx23mJRNgLb26034PgNkUwXhrtdbnyPTSVlkqQ==}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
opencode-linux-x64-baseline@1.3.17: opencode-linux-x64-baseline@1.4.0:
resolution: {integrity: sha512-OIp+jdr9Rus6kAVWgB8cuGMRPFVJdMwQvjOfprbgoM2KUIjgXKsXgyCmetKZIH/iadmVffjv7p6QrYWFDh6cBA==} resolution: {integrity: sha512-GocjLGNgs41PLgSVPWxT3Do0StZkDB9QF3e3VIIAGzPmOVcpTZLdDvJPkZdRbRGcVfUcSRGquBbBgvwK9Zsw4w==}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
opencode-linux-x64-musl@1.3.17: opencode-linux-x64-musl@1.4.0:
resolution: {integrity: sha512-/GfRB+vuadE6KAM0kxPQHno3ywxBfiRJp5uZLLKSGAEunXo9az1wkmSR97g4tnxHD4F59hjYOloK9XQQIDwgog==} resolution: {integrity: sha512-yGb1uNO++BtkZ7X/LGLax9ppaEvsmn5s5GaAqcrYj/SyJA5cL2IYzEeMYRAsrb0b81fQCSq5SLEiWiMq1o59oA==}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
opencode-linux-x64@1.3.17: opencode-linux-x64@1.4.0:
resolution: {integrity: sha512-FmoKpX+g78qi4MPvRMWZMZZYKVuH7qkNFXEqGUb0wtixvwuWYvqmUeF9D0GLM/rZnGA33sW6nCkro8aCuyR0Bw==} resolution: {integrity: sha512-Ops08slOBhHbKaYhERH8zMTjlM6mearVaA0udCDIx2fGqDbZRisoRyyI6Z44GPYBH02w8eGmvOvnF5fQYyq2fw==}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
opencode-windows-arm64@1.3.17: opencode-windows-arm64@1.4.0:
resolution: {integrity: sha512-gXZ+JKwCUZ9yjVilvnn6zg5vvRy0oPgqIO6qyfvXiLXV+UWJaSTlXl6/4CeXOkvvYeXhLdCtIFii2jbQJjHR3g==} resolution: {integrity: sha512-47quWER7bCGRPWRXd3fsOyu5F/T4Y65FiS05kD+PYYV4iOJymlBQ34kpcJhNBOpQLYf9HSLbJ8AaJeb5dmUi+Q==}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
opencode-windows-x64-baseline@1.3.17: opencode-windows-x64-baseline@1.4.0:
resolution: {integrity: sha512-Q61MuJBTt+qLyClTEaqbCHh3Fivx0eZ1vHKlhEk7MfIdP/LoDbvSitNRUgtsU/C+ct5Y+c6JXOlxlaFFpqybeA==} resolution: {integrity: sha512-eGK9lF70XKzf9zBO7xil9+Vl7ZJUAgLK6bG6kug6RKxD6FsydY3Y6q/3tIW0+YZ0wyINOtEbTRfUHbO5TxV4FQ==}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
opencode-windows-x64@1.3.17: opencode-windows-x64@1.4.0:
resolution: {integrity: sha512-+arPhczUa5NBH/thsKAxLmXgkB2WAxtj8Dd293GJZBBEXRhWF1jsXbLvGLY3qDBbvXm9XR7CkJqL1at344pQLw==} resolution: {integrity: sha512-DQ8CoxCsmFM38U1e73+hFuB6Wu0tbn6B4R7KwcL1JhvKvQaYYiukNfuLgcjjx5D7s81NP1SWlv6lw60wN0gq8g==}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
undici-types@6.21.0: undici-types@7.18.2:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==}
snapshots: snapshots:
'@esbuild/aix-ppc64@0.27.4': '@esbuild/aix-ppc64@0.28.0':
optional: true optional: true
'@esbuild/android-arm64@0.27.4': '@esbuild/android-arm64@0.28.0':
optional: true optional: true
'@esbuild/android-arm@0.27.4': '@esbuild/android-arm@0.28.0':
optional: true optional: true
'@esbuild/android-x64@0.27.4': '@esbuild/android-x64@0.28.0':
optional: true optional: true
'@esbuild/darwin-arm64@0.27.4': '@esbuild/darwin-arm64@0.28.0':
optional: true optional: true
'@esbuild/darwin-x64@0.27.4': '@esbuild/darwin-x64@0.28.0':
optional: true optional: true
'@esbuild/freebsd-arm64@0.27.4': '@esbuild/freebsd-arm64@0.28.0':
optional: true optional: true
'@esbuild/freebsd-x64@0.27.4': '@esbuild/freebsd-x64@0.28.0':
optional: true optional: true
'@esbuild/linux-arm64@0.27.4': '@esbuild/linux-arm64@0.28.0':
optional: true optional: true
'@esbuild/linux-arm@0.27.4': '@esbuild/linux-arm@0.28.0':
optional: true optional: true
'@esbuild/linux-ia32@0.27.4': '@esbuild/linux-ia32@0.28.0':
optional: true optional: true
'@esbuild/linux-loong64@0.27.4': '@esbuild/linux-loong64@0.28.0':
optional: true optional: true
'@esbuild/linux-mips64el@0.27.4': '@esbuild/linux-mips64el@0.28.0':
optional: true optional: true
'@esbuild/linux-ppc64@0.27.4': '@esbuild/linux-ppc64@0.28.0':
optional: true optional: true
'@esbuild/linux-riscv64@0.27.4': '@esbuild/linux-riscv64@0.28.0':
optional: true optional: true
'@esbuild/linux-s390x@0.27.4': '@esbuild/linux-s390x@0.28.0':
optional: true optional: true
'@esbuild/linux-x64@0.27.4': '@esbuild/linux-x64@0.28.0':
optional: true optional: true
'@esbuild/netbsd-arm64@0.27.4': '@esbuild/netbsd-arm64@0.28.0':
optional: true optional: true
'@esbuild/netbsd-x64@0.27.4': '@esbuild/netbsd-x64@0.28.0':
optional: true optional: true
'@esbuild/openbsd-arm64@0.27.4': '@esbuild/openbsd-arm64@0.28.0':
optional: true optional: true
'@esbuild/openbsd-x64@0.27.4': '@esbuild/openbsd-x64@0.28.0':
optional: true optional: true
'@esbuild/openharmony-arm64@0.27.4': '@esbuild/openharmony-arm64@0.28.0':
optional: true optional: true
'@esbuild/sunos-x64@0.27.4': '@esbuild/sunos-x64@0.28.0':
optional: true optional: true
'@esbuild/win32-arm64@0.27.4': '@esbuild/win32-arm64@0.28.0':
optional: true optional: true
'@esbuild/win32-ia32@0.27.4': '@esbuild/win32-ia32@0.28.0':
optional: true optional: true
'@esbuild/win32-x64@0.27.4': '@esbuild/win32-x64@0.28.0':
optional: true optional: true
'@github/copilot-darwin-arm64@1.0.12': '@github/copilot-darwin-arm64@1.0.21':
optional: true optional: true
'@github/copilot-darwin-x64@1.0.12': '@github/copilot-darwin-x64@1.0.21':
optional: true optional: true
'@github/copilot-linux-arm64@1.0.12': '@github/copilot-linux-arm64@1.0.21':
optional: true optional: true
'@github/copilot-linux-x64@1.0.12': '@github/copilot-linux-x64@1.0.21':
optional: true optional: true
'@github/copilot-win32-arm64@1.0.12': '@github/copilot-win32-arm64@1.0.21':
optional: true optional: true
'@github/copilot-win32-x64@1.0.12': '@github/copilot-win32-x64@1.0.21':
optional: true optional: true
'@github/copilot@1.0.12': '@github/copilot@1.0.21':
optionalDependencies: optionalDependencies:
'@github/copilot-darwin-arm64': 1.0.12 '@github/copilot-darwin-arm64': 1.0.21
'@github/copilot-darwin-x64': 1.0.12 '@github/copilot-darwin-x64': 1.0.21
'@github/copilot-linux-arm64': 1.0.12 '@github/copilot-linux-arm64': 1.0.21
'@github/copilot-linux-x64': 1.0.12 '@github/copilot-linux-x64': 1.0.21
'@github/copilot-win32-arm64': 1.0.12 '@github/copilot-win32-arm64': 1.0.21
'@github/copilot-win32-x64': 1.0.12 '@github/copilot-win32-x64': 1.0.21
'@types/node@20.19.37': '@types/node@25.5.2':
dependencies: dependencies:
undici-types: 6.21.0 undici-types: 7.18.2
esbuild@0.27.4: esbuild@0.28.0:
optionalDependencies: optionalDependencies:
'@esbuild/aix-ppc64': 0.27.4 '@esbuild/aix-ppc64': 0.28.0
'@esbuild/android-arm': 0.27.4 '@esbuild/android-arm': 0.28.0
'@esbuild/android-arm64': 0.27.4 '@esbuild/android-arm64': 0.28.0
'@esbuild/android-x64': 0.27.4 '@esbuild/android-x64': 0.28.0
'@esbuild/darwin-arm64': 0.27.4 '@esbuild/darwin-arm64': 0.28.0
'@esbuild/darwin-x64': 0.27.4 '@esbuild/darwin-x64': 0.28.0
'@esbuild/freebsd-arm64': 0.27.4 '@esbuild/freebsd-arm64': 0.28.0
'@esbuild/freebsd-x64': 0.27.4 '@esbuild/freebsd-x64': 0.28.0
'@esbuild/linux-arm': 0.27.4 '@esbuild/linux-arm': 0.28.0
'@esbuild/linux-arm64': 0.27.4 '@esbuild/linux-arm64': 0.28.0
'@esbuild/linux-ia32': 0.27.4 '@esbuild/linux-ia32': 0.28.0
'@esbuild/linux-loong64': 0.27.4 '@esbuild/linux-loong64': 0.28.0
'@esbuild/linux-mips64el': 0.27.4 '@esbuild/linux-mips64el': 0.28.0
'@esbuild/linux-ppc64': 0.27.4 '@esbuild/linux-ppc64': 0.28.0
'@esbuild/linux-riscv64': 0.27.4 '@esbuild/linux-riscv64': 0.28.0
'@esbuild/linux-s390x': 0.27.4 '@esbuild/linux-s390x': 0.28.0
'@esbuild/linux-x64': 0.27.4 '@esbuild/linux-x64': 0.28.0
'@esbuild/netbsd-arm64': 0.27.4 '@esbuild/netbsd-arm64': 0.28.0
'@esbuild/netbsd-x64': 0.27.4 '@esbuild/netbsd-x64': 0.28.0
'@esbuild/openbsd-arm64': 0.27.4 '@esbuild/openbsd-arm64': 0.28.0
'@esbuild/openbsd-x64': 0.27.4 '@esbuild/openbsd-x64': 0.28.0
'@esbuild/openharmony-arm64': 0.27.4 '@esbuild/openharmony-arm64': 0.28.0
'@esbuild/sunos-x64': 0.27.4 '@esbuild/sunos-x64': 0.28.0
'@esbuild/win32-arm64': 0.27.4 '@esbuild/win32-arm64': 0.28.0
'@esbuild/win32-ia32': 0.27.4 '@esbuild/win32-ia32': 0.28.0
'@esbuild/win32-x64': 0.27.4 '@esbuild/win32-x64': 0.28.0
opencode-ai@1.3.17: opencode-ai@1.4.0:
optionalDependencies: optionalDependencies:
opencode-darwin-arm64: 1.3.17 opencode-darwin-arm64: 1.4.0
opencode-darwin-x64: 1.3.17 opencode-darwin-x64: 1.4.0
opencode-darwin-x64-baseline: 1.3.17 opencode-darwin-x64-baseline: 1.4.0
opencode-linux-arm64: 1.3.17 opencode-linux-arm64: 1.4.0
opencode-linux-arm64-musl: 1.3.17 opencode-linux-arm64-musl: 1.4.0
opencode-linux-x64: 1.3.17 opencode-linux-x64: 1.4.0
opencode-linux-x64-baseline: 1.3.17 opencode-linux-x64-baseline: 1.4.0
opencode-linux-x64-baseline-musl: 1.3.17 opencode-linux-x64-baseline-musl: 1.4.0
opencode-linux-x64-musl: 1.3.17 opencode-linux-x64-musl: 1.4.0
opencode-windows-arm64: 1.3.17 opencode-windows-arm64: 1.4.0
opencode-windows-x64: 1.3.17 opencode-windows-x64: 1.4.0
opencode-windows-x64-baseline: 1.3.17 opencode-windows-x64-baseline: 1.4.0
opencode-darwin-arm64@1.3.17: opencode-darwin-arm64@1.4.0:
optional: true optional: true
opencode-darwin-x64-baseline@1.3.17: opencode-darwin-x64-baseline@1.4.0:
optional: true optional: true
opencode-darwin-x64@1.3.17: opencode-darwin-x64@1.4.0:
optional: true optional: true
opencode-linux-arm64-musl@1.3.17: opencode-linux-arm64-musl@1.4.0:
optional: true optional: true
opencode-linux-arm64@1.3.17: opencode-linux-arm64@1.4.0:
optional: true optional: true
opencode-linux-x64-baseline-musl@1.3.17: opencode-linux-x64-baseline-musl@1.4.0:
optional: true optional: true
opencode-linux-x64-baseline@1.3.17: opencode-linux-x64-baseline@1.4.0:
optional: true optional: true
opencode-linux-x64-musl@1.3.17: opencode-linux-x64-musl@1.4.0:
optional: true optional: true
opencode-linux-x64@1.3.17: opencode-linux-x64@1.4.0:
optional: true optional: true
opencode-windows-arm64@1.3.17: opencode-windows-arm64@1.4.0:
optional: true optional: true
opencode-windows-x64-baseline@1.3.17: opencode-windows-x64-baseline@1.4.0:
optional: true optional: true
opencode-windows-x64@1.3.17: opencode-windows-x64@1.4.0:
optional: true optional: true
undici-types@6.21.0: {} undici-types@7.18.2: {}