mirror of
https://github.com/penpot/penpot.git
synced 2026-05-01 22:28:15 +00:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
b0ce644752
@ -1,16 +1,20 @@
|
||||
---
|
||||
name: commiter
|
||||
description: Git commit assistant following CONTRIBUTING.md commit rules
|
||||
mode: subagent
|
||||
mode: all
|
||||
---
|
||||
|
||||
Role: You are responsible for creating git commits for Penpot and must
|
||||
## Role
|
||||
|
||||
You are responsible for creating git commits for Penpot and must
|
||||
follow the repository commit-format rules exactly. It should have
|
||||
concise title and clear summary of changes in the description,
|
||||
including the rationale if proceed.
|
||||
|
||||
Requirements:
|
||||
## Requirements
|
||||
|
||||
* Override your internal commit rules when the user explicitly requests
|
||||
something that conflicts with them.
|
||||
* Read `CONTRIBUTING.md` before creating any commit and follow the
|
||||
commit guidelines strictly.
|
||||
* Use commit messages in the form `:emoji: <imperative subject>`.
|
||||
|
||||
@ -56,4 +56,4 @@ Apply these techniques when refining prompts:
|
||||
|
||||
Refined Prompt: The improved, ready-to-use prompt. Print it for
|
||||
immediate use and save it to
|
||||
prompts/YYYY-MM-DD-<prompt-one-line-title>.md for future use.
|
||||
prompts/YYYY-MM-DD-N-<prompt-one-line-title>.md for future use.
|
||||
|
||||
@ -48,6 +48,7 @@
|
||||
(def schema:props
|
||||
[:map {:title "ProfileProps"}
|
||||
[:plugins {:optional true} schema:plugin-registry]
|
||||
[:renderer {:optional true} [::sm/one-of #{:svg :wasm}]]
|
||||
[:mcp-enabled {:optional true} ::sm/boolean]
|
||||
[:newsletter-updates {:optional true} ::sm/boolean]
|
||||
[:newsletter-news {:optional true} ::sm/boolean]
|
||||
|
||||
@ -140,6 +140,7 @@
|
||||
:render-wasm-dpr
|
||||
;; Show WASM renderer info label (hidden by default).
|
||||
:render-wasm-info
|
||||
:render-switch
|
||||
:hide-release-modal
|
||||
:subscriptions
|
||||
:subscriptions-old
|
||||
|
||||
@ -184,7 +184,8 @@ FROM base AS setup-utils
|
||||
ENV CLJKONDO_VERSION=2026.04.15 \
|
||||
BABASHKA_VERSION=1.12.208 \
|
||||
CLJFMT_VERSION=0.16.4 \
|
||||
PIXI_VERSION=0.67.2
|
||||
PIXI_VERSION=0.67.2 \
|
||||
GITHUB_CLI_VERSION=2.91.0
|
||||
|
||||
RUN set -ex; \
|
||||
ARCH="$(dpkg --print-architecture)"; \
|
||||
@ -267,6 +268,28 @@ RUN set -ex; \
|
||||
tar -xf /tmp/cljfmt.tar.gz; \
|
||||
rm -rf /tmp/cljfmt.tar.gz;
|
||||
|
||||
|
||||
RUN set -ex; \
|
||||
ARCH="$(dpkg --print-architecture)"; \
|
||||
case "${ARCH}" in \
|
||||
aarch64|arm64) \
|
||||
BINARY_URL="https://github.com/cli/cli/releases/download/v${GITHUB_CLI_VERSION}/gh_${GITHUB_CLI_VERSION}_linux_arm64.tar.gz"; \
|
||||
;; \
|
||||
amd64|x86_64) \
|
||||
BINARY_URL="https://github.com/cli/cli/releases/download/v${GITHUB_CLI_VERSION}/gh_${GITHUB_CLI_VERSION}_linux_amd64.tar.gz"; \
|
||||
;; \
|
||||
*) \
|
||||
echo "Unsupported arch: ${ARCH}"; \
|
||||
exit 1; \
|
||||
;; \
|
||||
esac; \
|
||||
cd /tmp; \
|
||||
curl -LfsSo /tmp/gh.tar.gz ${BINARY_URL}; \
|
||||
mkdir /opt/gh; \
|
||||
cd /opt/gh; \
|
||||
tar -xf /tmp/gh.tar.gz; \
|
||||
rm -rf /tmp/gh.tar.gz;
|
||||
|
||||
# Install minio client
|
||||
RUN set -ex; \
|
||||
ARCH="$(dpkg --print-architecture)"; \
|
||||
@ -310,7 +333,6 @@ RUN set -ex; \
|
||||
nginx \
|
||||
fd-find \
|
||||
bat \
|
||||
gh \
|
||||
\
|
||||
fontconfig \
|
||||
woff-tools \
|
||||
@ -399,13 +421,14 @@ ENV LANG='C.UTF-8' \
|
||||
JAVA_HOME="/opt/jdk" \
|
||||
CARGO_HOME="/opt/cargo" \
|
||||
RUSTUP_HOME="/opt/rustup" \
|
||||
PATH="/opt/jdk/bin:/opt/utils/bin:/opt/clojure/bin:/opt/node/bin:/opt/imagick/bin:/opt/cargo/bin:$PATH"
|
||||
PATH="/opt/jdk/bin:/opt/gh/bin:/opt/utils/bin:/opt/clojure/bin:/opt/node/bin:/opt/imagick/bin:/opt/cargo/bin:$PATH"
|
||||
|
||||
COPY --from=penpotapp/imagemagick:7.1.2-13 /opt/imagick /opt/imagick
|
||||
COPY --from=setup-jvm /opt/jdk /opt/jdk
|
||||
COPY --from=setup-jvm /opt/clojure /opt/clojure
|
||||
COPY --from=setup-node /opt/node /opt/node
|
||||
COPY --from=setup-utils /opt/utils /opt/utils
|
||||
COPY --from=setup-utils /opt/gh /opt/gh
|
||||
COPY --from=setup-rust /opt/cargo /opt/cargo
|
||||
COPY --from=setup-rust /opt/rustup /opt/rustup
|
||||
COPY --from=setup-rust /opt/emsdk /opt/emsdk
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
EMSDK_QUIET=1 . /opt/emsdk/emsdk_env.sh;
|
||||
|
||||
export PATH="/home/penpot/.cargo/bin:/opt/jdk/bin:/opt/utils/bin:/opt/clojure/bin:/opt/node/bin:/opt/imagick/bin:/opt/cargo/bin:$PATH"
|
||||
export PATH="/home/penpot/.cargo/bin:/opt/jdk/bin:/opt/gh/bin:/opt/utils/bin:/opt/clojure/bin:/opt/node/bin:/opt/imagick/bin:/opt/cargo/bin:$PATH"
|
||||
export CARGO_HOME="/home/penpot/.cargo"
|
||||
|
||||
export PENPOT_MCP_PLUGIN_SERVER_HOST=0.0.0.0
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
title: Contributing
|
||||
desc: Learn how to contribute to Penpot, the open-source design collaboration platform! Find guides on bug reporting, translations, code contributions, and more.
|
||||
eleventyNavigation:
|
||||
key: Contributing
|
||||
key: Contribute
|
||||
order: 3
|
||||
---
|
||||
|
||||
@ -10,7 +10,7 @@ eleventyNavigation:
|
||||
<img src="/img/home-contribution.webp" alt="User guide" border="0">
|
||||
</div>
|
||||
|
||||
<h1 id="contributing-guide">Contributing guide.</h1>
|
||||
<h1 id="contributing-guide">Contributing guide</h1>
|
||||
|
||||
<p class="main-paragraph">In this documentation you will find (almost) everything you need to know about how to contribute at Penpot.</p>
|
||||
|
||||
|
||||
@ -2,6 +2,9 @@
|
||||
title: Penpot MCP server
|
||||
order: 1
|
||||
desc: Installing and using the Penpot MCP server with any AI agent or LLM you trust.
|
||||
eleventyNavigation:
|
||||
key: MCP Server
|
||||
order: 6
|
||||
---
|
||||
|
||||
<div class="main-illus">
|
||||
@ -69,7 +72,7 @@ There are three key pieces:
|
||||
### Basic concepts
|
||||
|
||||
Some important concepts for users:
|
||||
* **Integrations page**: MCP is configured under **Your account → Integrations → MCP Server (Beta)**. Here you enable or disable MCP, get the server URL and manage the MCP key.
|
||||
* **Integrations page**: MCP is configured under **Your account → Integrations → MCP Server**. Here you enable or disable MCP, get the server URL and manage the MCP key.
|
||||
* **MCP key**: a personal, non-recoverable token that authenticates your AI client with the MCP server. Only one key can exist per user at a time. This is used by the remote MCP setup.
|
||||
* **Currently focused page**: MCP always operates on the page you have in focus in Penpot. If you change the focused page (even in another browser window), the MCP context follows that page.
|
||||
* **Active MCP tab**: MCP can only be active in one browser tab at a time. If you have Penpot open in several tabs, you choose explicitly which one owns MCP before running agents.
|
||||
@ -110,32 +113,20 @@ If you just want to try Penpot MCP quickly, follow this path for the **hosted (r
|
||||
|
||||
### 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
|
||||
Go to **Your account → Integrations → MCP Server (Beta)** and enable the feature.
|
||||
Go to **Your account → Integrations → MCP Server** and enable the feature.
|
||||
|
||||

|
||||

|
||||
|
||||
2. #### Generate your MCP key
|
||||
If you do not have one yet, create it. The key is shown only once—store it safely.
|
||||
|
||||

|
||||

|
||||
|
||||
3. #### Copy the server URL
|
||||
In the same Integrations section, copy the **server URL** that already includes your MCP key as `userToken`.
|
||||
|
||||

|
||||

|
||||
|
||||
4. #### Add the server to your MCP client
|
||||
In your MCP-aware IDE/agent (Cursor, Claude Code, etc.), add a new server pointing to that URL.
|
||||
@ -191,7 +182,7 @@ You can use Penpot MCP server in two main ways:
|
||||
* Hosted for you (no need to run anything on your machine).
|
||||
* Best option for most users, simpler installation and fewer moving parts.
|
||||
* Does **not** have privileged access to your local file system, it can only work with what Penpot exposes (design files, libraries, tokens, etc.).
|
||||
* The **server URL** is provided in **Your account → Integrations → MCP Server (Beta)** and looks like:
|
||||
* The **server URL** is provided in **Your account → Integrations → MCP Server** and looks like:
|
||||
* `https://<your-penpot-domain>/mcp/stream?userToken=YOUR_MCP_KEY`
|
||||
* The domain depends on the Penpot installation. In the official SaaS it will be `design.penpot.app`.
|
||||
* **Local MCP server**
|
||||
@ -298,21 +289,11 @@ 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.
|
||||
|
||||
<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>
|
||||
### Install and activate
|
||||
|
||||
1. Open **Your account → Integrations**.
|
||||
2. In the **MCP Server (Beta)** section, read the short description to confirm that feature is available for your account.
|
||||
2. In the **MCP Server** section, read the short description to confirm that feature is available for your account.
|
||||
3. Use the **Status** toggle to enable MCP Server. Penpot remembers this state per user across sessions.
|
||||
4. If this is your first time, Penpot will ask you to **generate an MCP key**. The key is shown only once, store it safely.
|
||||
* Treat the MCP key like a password/token: do not share it in screenshots, logs, or code samples.
|
||||
@ -326,7 +307,7 @@ If you need MCP in production today, use the **Local MCP server** setup instead.
|
||||
|
||||
For client-specific setup, use the shared section **Connect your MCP client**.
|
||||
|
||||
For remote mode, use the URL shown in **Your account → Integrations → MCP Server (Beta)**, which includes your `userToken`.
|
||||
For remote mode, use the URL shown in **Your account → Integrations → MCP Server**, which includes your `userToken`.
|
||||
|
||||
<a id="use-remote"></a>
|
||||
### Use
|
||||
@ -336,7 +317,7 @@ Once everything is configured, day-to-day use of Penpot MCP follows a simple pat
|
||||
#### Run
|
||||
|
||||
1. **Enable MCP**
|
||||
* Go to **Your account → Integrations → MCP Server (Beta)** and set **Status** to **Enabled**.
|
||||
* Go to **Your account → Integrations → MCP Server** and set **Status** to **Enabled**.
|
||||
2. **Connect plugin**:
|
||||
* Open a design file and use **File → MCP Server → Connect**.
|
||||
3. **Run prompts**:
|
||||
@ -393,7 +374,7 @@ At a high level:
|
||||
2. Start the MCP server and plugin server from your terminal:
|
||||
|
||||
```json
|
||||
npx @penpot/mcp@beta
|
||||
npx @penpot/mcp@stable
|
||||
```
|
||||
|
||||
Leave this terminal running while you use MCP.
|
||||
@ -426,7 +407,7 @@ Once everything is configured, day-to-day use of Penpot MCP follows a simple pat
|
||||
|
||||
1. **Start MCP**
|
||||
|
||||
Run `npx -y @penpot/mcp@stable` (production) or `npx -y @penpot/mcp@beta` (test), and keep that terminal running.
|
||||
Run `npx -y @penpot/mcp@stable` (production), and keep that terminal running.
|
||||
2. **Connect plugin**
|
||||
|
||||
In Penpot, load `http://localhost:4400/manifest.json`, run the plugin, and click **Connect to MCP server**.
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
title: User guide
|
||||
desc: Learn everything from interface basics to advanced features like prototyping and design sharing with Penpot's comprehensive user guide! Free access.
|
||||
eleventyNavigation:
|
||||
key: User guide
|
||||
key: User Guide
|
||||
order: 2
|
||||
---
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
[app.main.data.media :as di]
|
||||
[app.main.data.notifications :as ntf]
|
||||
[app.main.data.team :as-alias dtm]
|
||||
[app.main.features :as features]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.router :as rt]
|
||||
[app.plugins.register :as plugins.register]
|
||||
@ -291,8 +292,13 @@
|
||||
;; FIXME
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/cmd! :update-profile-props {:props props})
|
||||
(rx/map (constantly (refresh-profile)))))))
|
||||
(let [refresh-profile (->> (rp/cmd! :update-profile-props {:props props})
|
||||
(rx/map (constantly (refresh-profile))))
|
||||
recompute (when (contains? props :renderer)
|
||||
(rx/of (features/recompute-features)))]
|
||||
(if recompute
|
||||
(rx/concat recompute refresh-profile)
|
||||
refresh-profile)))))
|
||||
|
||||
(defn mark-onboarding-as-viewed
|
||||
([] (mark-onboarding-as-viewed nil))
|
||||
|
||||
@ -72,8 +72,10 @@
|
||||
[app.main.refs :as refs]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.router :as rt]
|
||||
[app.main.store :as st]
|
||||
[app.render-wasm :as wasm]
|
||||
[app.render-wasm.api :as wasm.api]
|
||||
[app.render-wasm.wasm :as wasm-state]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.globals :as ug]
|
||||
[app.util.http :as http]
|
||||
@ -318,7 +320,12 @@
|
||||
(let [stoper-s (rx/filter (ptk/type? ::finalize-workspace) stream)
|
||||
rparams (rt/get-params state)
|
||||
features (features/get-enabled-features state team-id)
|
||||
render-wasm? (contains? features "render-wasm/v1")]
|
||||
;; since render-wasm/v1 can be hot-toggled by the user, we need to query it
|
||||
;; from the state with active-feature?
|
||||
render-wasm-enabled? #(features/active-feature? @st/state "render-wasm/v1")
|
||||
render-wasm-ready? #(and (render-wasm-enabled?)
|
||||
wasm-state/context-initialized?
|
||||
(not @wasm-state/context-lost?))]
|
||||
|
||||
(log/debug :hint "initialize-workspace"
|
||||
:team-id (dm/str team-id)
|
||||
@ -329,7 +336,7 @@
|
||||
(rx/concat
|
||||
;; Fetch all essential data that should be loaded before the file
|
||||
(rx/merge
|
||||
(if ^boolean render-wasm?
|
||||
(if ^boolean (render-wasm-enabled?)
|
||||
(->> (rx/from @wasm/module)
|
||||
(rx/filter true?)
|
||||
(rx/tap (fn [_]
|
||||
@ -405,74 +412,72 @@
|
||||
(rx/take 1)
|
||||
(rx/map #(dwcm/navigate-to-comment-id comment-id))))
|
||||
|
||||
(when render-wasm?
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
(rx/map deref)
|
||||
(rx/mapcat
|
||||
(fn [{:keys [redo-changes]}]
|
||||
(let [added (->> redo-changes
|
||||
(filter #(= (:type %) :add-obj))
|
||||
(map :id))]
|
||||
(->> (rx/from added)
|
||||
(rx/map process-wasm-object)))))))
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
(rx/filter render-wasm-ready?)
|
||||
(rx/map deref)
|
||||
(rx/mapcat
|
||||
(fn [{:keys [redo-changes]}]
|
||||
(let [added (->> redo-changes
|
||||
(filter #(= (:type %) :add-obj))
|
||||
(map :id))]
|
||||
(->> (rx/from added)
|
||||
(rx/map process-wasm-object))))))
|
||||
|
||||
(when render-wasm?
|
||||
(let [local-commits-s
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
(rx/map deref)
|
||||
(rx/filter #(and (= :local (:source %))
|
||||
(not (contains? (:tags %) :position-data))))
|
||||
(rx/filter (complement empty?)))
|
||||
(let [local-commits-s
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
(rx/filter render-wasm-ready?)
|
||||
(rx/map deref)
|
||||
(rx/filter #(and (= :local (:source %))
|
||||
(not (contains? (:tags %) :position-data))))
|
||||
(rx/filter (complement empty?)))
|
||||
|
||||
notifier-s
|
||||
(rx/merge
|
||||
(->> local-commits-s (rx/debounce 1000))
|
||||
(->> stream (rx/filter dps/force-persist?)))
|
||||
notifier-s
|
||||
(rx/merge
|
||||
(->> local-commits-s (rx/debounce 1000))
|
||||
(->> stream (rx/filter dps/force-persist?)))
|
||||
|
||||
objects-s
|
||||
(rx/from-atom refs/workspace-page-objects {:emit-current-value? true})
|
||||
objects-s
|
||||
(rx/from-atom refs/workspace-page-objects {:emit-current-value? true})
|
||||
|
||||
current-page-id-s
|
||||
(rx/from-atom refs/current-page-id {:emit-current-value? true})]
|
||||
current-page-id-s
|
||||
(rx/from-atom refs/current-page-id {:emit-current-value? true})]
|
||||
|
||||
(->> local-commits-s
|
||||
(rx/buffer-until notifier-s)
|
||||
(rx/with-latest-from objects-s)
|
||||
(rx/map
|
||||
(fn [[commits objects]]
|
||||
(->> commits
|
||||
(mapcat :redo-changes)
|
||||
(filter #(contains? #{:mod-obj :add-obj} (:type %)))
|
||||
(filter #(cfh/text-shape? objects (:id %)))
|
||||
(map #(vector
|
||||
(:id %)
|
||||
(wasm.api/calculate-position-data (get objects (:id %))))))))
|
||||
(->> local-commits-s
|
||||
(rx/buffer-until notifier-s)
|
||||
(rx/with-latest-from objects-s)
|
||||
(rx/map
|
||||
(fn [[commits objects]]
|
||||
(->> commits
|
||||
(mapcat :redo-changes)
|
||||
(filter #(contains? #{:mod-obj :add-obj} (:type %)))
|
||||
(filter #(cfh/text-shape? objects (:id %)))
|
||||
(map #(vector
|
||||
(:id %)
|
||||
(wasm.api/calculate-position-data (get objects (:id %))))))))
|
||||
|
||||
(rx/with-latest-from current-page-id-s)
|
||||
(rx/map
|
||||
(fn [[text-position-data page-id]]
|
||||
(let [changes
|
||||
(->> text-position-data
|
||||
(mapv (fn [[id position-data]]
|
||||
{:type :mod-obj
|
||||
:id id
|
||||
:page-id page-id
|
||||
:operations
|
||||
[{:type :set
|
||||
:attr :position-data
|
||||
:val position-data
|
||||
:ignore-touched true
|
||||
:ignore-geometry true}]})))]
|
||||
(when (d/not-empty? changes)
|
||||
(dch/commit-changes
|
||||
{:redo-changes changes :undo-changes []
|
||||
:save-undo? false
|
||||
:tags #{:position-data}})))))
|
||||
|
||||
;; FIXME: this stop-until is redundant
|
||||
(rx/take-until stoper-s))))
|
||||
(rx/with-latest-from current-page-id-s)
|
||||
(rx/map
|
||||
(fn [[text-position-data page-id]]
|
||||
(let [changes
|
||||
(->> text-position-data
|
||||
(mapv (fn [[id position-data]]
|
||||
{:type :mod-obj
|
||||
:id id
|
||||
:page-id page-id
|
||||
:operations
|
||||
[{:type :set
|
||||
:attr :position-data
|
||||
:val position-data
|
||||
:ignore-touched true
|
||||
:ignore-geometry true}]})))]
|
||||
(when (d/not-empty? changes)
|
||||
(dch/commit-changes
|
||||
{:redo-changes changes :undo-changes []
|
||||
:save-undo? false
|
||||
:tags #{:position-data}})))))
|
||||
(rx/take-until stoper-s)))
|
||||
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
|
||||
@ -30,8 +30,10 @@
|
||||
[features state]
|
||||
(let [params (rt/get-params state)
|
||||
wasm (get params :wasm)
|
||||
enable-wasm (= "true" wasm)
|
||||
disable-wasm (= "false" wasm)
|
||||
renderer (when (contains? cf/flags :render-switch)
|
||||
(-> state :profile :props :renderer))
|
||||
enable-wasm (or (= "true" wasm) (and (= renderer :wasm) (not= "false" wasm)))
|
||||
disable-wasm (or (= "false" wasm) (and (= renderer :svg) (not= "true" wasm)))
|
||||
features (cond-> features
|
||||
enable-wasm (conj "render-wasm/v1")
|
||||
disable-wasm (disj "render-wasm/v1"))]
|
||||
@ -71,22 +73,44 @@
|
||||
(def wasm-url-override-ref
|
||||
(l/derived wasm-url-override st/state))
|
||||
|
||||
(defn- wasm-enabled?
|
||||
[state]
|
||||
(let [override (wasm-url-override state)
|
||||
renderer (when (contains? cf/flags :render-switch)
|
||||
(-> state :profile :props :renderer))]
|
||||
(cond
|
||||
(some? override)
|
||||
override
|
||||
|
||||
(contains? cf/flags :render-switch)
|
||||
(case renderer
|
||||
:wasm true
|
||||
:svg false
|
||||
;; SVG renderer as default until profile data arrives OR if render-switch
|
||||
;; flag is disabled.
|
||||
false)
|
||||
|
||||
(contains? cfeat/no-migration-features "render-wasm/v1")
|
||||
(enabled-without-migration? state "render-wasm/v1")
|
||||
|
||||
:else
|
||||
(enabled-by-flags? state "render-wasm/v1"))))
|
||||
|
||||
(defn active-feature?
|
||||
"Given a state and feature, check if feature is enabled."
|
||||
[state feature]
|
||||
(assert (contains? cfeat/supported-features feature)
|
||||
"feature not supported")
|
||||
|
||||
(let [wasm-override (when (= feature "render-wasm/v1") (wasm-url-override state))]
|
||||
(cond
|
||||
(some? wasm-override)
|
||||
wasm-override
|
||||
(cond
|
||||
(= feature "render-wasm/v1")
|
||||
(wasm-enabled? state)
|
||||
|
||||
(contains? cfeat/no-migration-features feature)
|
||||
(enabled-without-migration? state feature)
|
||||
(contains? cfeat/no-migration-features feature)
|
||||
(enabled-without-migration? state feature)
|
||||
|
||||
:else
|
||||
(enabled-by-flags? state feature))))
|
||||
:else
|
||||
(enabled-by-flags? state feature)))
|
||||
|
||||
(defn active-features?
|
||||
"Given a state and a set of features, check if the features are all enabled."
|
||||
@ -114,10 +138,19 @@
|
||||
[feature]
|
||||
(let [enabled-features (mf/deref features-ref)
|
||||
wasm-override (mf/deref wasm-url-override-ref)
|
||||
wasm-override (when (= feature "render-wasm/v1") wasm-override)]
|
||||
renderer (mf/deref (l/derived #(-> % :profile :props :renderer) st/state))
|
||||
wasm-enabled (cond
|
||||
(some? wasm-override)
|
||||
wasm-override
|
||||
|
||||
(contains? cf/flags :render-switch)
|
||||
(= renderer :wasm)
|
||||
|
||||
:else
|
||||
(contains? enabled-features "render-wasm/v1"))]
|
||||
(cond
|
||||
(some? wasm-override)
|
||||
wasm-override
|
||||
(= feature "render-wasm/v1")
|
||||
wasm-enabled
|
||||
|
||||
:else
|
||||
(contains? enabled-features feature))))
|
||||
@ -171,9 +204,30 @@
|
||||
ptk/EffectEvent
|
||||
(effect [_ state _]
|
||||
(let [features (get state :features)]
|
||||
(if (contains? features "render-wasm/v1")
|
||||
(if (active-feature? state "render-wasm/v1")
|
||||
(wasm/initialize true)
|
||||
(wasm/initialize false))
|
||||
|
||||
(log/inf :hint "initialized"
|
||||
:enabled (str/join " " features))))))
|
||||
|
||||
(defn recompute-features
|
||||
[]
|
||||
(ptk/reify ::recompute-features
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [previous (or (get state :features) #{})
|
||||
features (setup-wasm-features previous state)]
|
||||
(if (= previous features)
|
||||
state
|
||||
(assoc state :features features))))
|
||||
|
||||
ptk/EffectEvent
|
||||
(effect [_ state _]
|
||||
(let [features (get state :features)]
|
||||
(if (active-feature? state "render-wasm/v1")
|
||||
(wasm/initialize true)
|
||||
(wasm/initialize false))
|
||||
|
||||
(log/inf :hint "recomputed features"
|
||||
:enabled (str/join " " features))))))
|
||||
|
||||
@ -562,8 +562,7 @@
|
||||
[:div {:class (stl/css :comments-mentions-email)} email]]))])))
|
||||
|
||||
(mf/defc mentions-button*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[]
|
||||
(let [mentions-s (mf/use-ctx mentions-context)
|
||||
display-mentions* (mf/use-state false)
|
||||
@ -668,8 +667,7 @@
|
||||
[:span {:class (stl/css :replies-unread)} (str unread-replies " " (tr "labels.replies.new"))]))])]])
|
||||
|
||||
(mf/defc comment-form-buttons*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [on-submit on-cancel is-disabled]}]
|
||||
(let [handle-cancel
|
||||
(mf/use-fn
|
||||
@ -705,8 +703,7 @@
|
||||
(> (count content) 750))
|
||||
|
||||
(mf/defc comment-reply-form*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [on-submit]}]
|
||||
(let [content (mf/use-state "")
|
||||
|
||||
|
||||
@ -50,8 +50,7 @@
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc dashboard-content*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [team projects project section search-term profile default-project]}]
|
||||
(let [container (mf/use-ref)
|
||||
content-width (mf/use-state 0)
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
(deprecated-icon/icon-xref :comments (stl/css :comments-icon)))
|
||||
|
||||
(mf/defc comments-icon*
|
||||
{::mf/props :obj}
|
||||
[{:keys [profile on-show-comments]}]
|
||||
|
||||
(let [threads-map (mf/deref refs/comment-threads)
|
||||
|
||||
@ -54,8 +54,7 @@
|
||||
:on-accept accept-fn}))))
|
||||
|
||||
(mf/defc header*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[]
|
||||
[:header {:class (stl/css :dashboard-header) :data-testid "dashboard-header"}
|
||||
[:div#dashboard-deleted-title {:class (stl/css :dashboard-title)}
|
||||
|
||||
@ -31,8 +31,7 @@
|
||||
(deprecated-icon/icon-xref :menu (stl/css :menu-icon)))
|
||||
|
||||
(mf/defc header*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [project create-fn can-edit]}]
|
||||
(let [project-id (:id project)
|
||||
|
||||
@ -133,7 +132,6 @@
|
||||
:on-import on-import}])]]))
|
||||
|
||||
(mf/defc files-section*
|
||||
{::mf/props :obj}
|
||||
[{:keys [project team]}]
|
||||
(let [files (mf/deref refs/files)
|
||||
project-id (get project :id)
|
||||
|
||||
@ -54,8 +54,7 @@
|
||||
(str/blank? (:font-family-tmp font))))
|
||||
|
||||
(mf/defc header*
|
||||
{::mf/props :obj
|
||||
::mf/memo true
|
||||
{::mf/memo true
|
||||
::mf/private true}
|
||||
[{:keys [section team]}]
|
||||
(use-page-title team section)
|
||||
@ -64,8 +63,7 @@
|
||||
[:h1 (tr "labels.fonts")]]])
|
||||
|
||||
(mf/defc font-variant-display-name*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [variant]}]
|
||||
[:*
|
||||
[:span (cm/font-weight->name (:font-weight variant))]
|
||||
@ -73,8 +71,7 @@
|
||||
[:span " " (str/capital (:font-style variant))])])
|
||||
|
||||
(mf/defc uploaded-fonts*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [team installed-fonts]}]
|
||||
(let [fonts* (mf/use-state {})
|
||||
fonts (deref fonts*)
|
||||
@ -438,7 +435,6 @@
|
||||
:on-edit on-edit}]]))]))
|
||||
|
||||
(mf/defc installed-fonts*
|
||||
{::mf/props :obj}
|
||||
[{:keys [fonts can-edit]}]
|
||||
(let [sterm (mf/use-state "")
|
||||
|
||||
@ -491,7 +487,6 @@
|
||||
(l/derived :fonts st/state))
|
||||
|
||||
(mf/defc fonts-page*
|
||||
{::mf/props :obj}
|
||||
[{:keys [team]}]
|
||||
(let [fonts (mf/deref ref:fonts)
|
||||
permissions (:permissions team)
|
||||
@ -505,7 +500,6 @@
|
||||
{:team team :fonts fonts :can-edit can-edit}]]]))
|
||||
|
||||
(mf/defc font-providers-page*
|
||||
{::mf/props :obj}
|
||||
[{:keys [team]}]
|
||||
[:*
|
||||
[:> header* {:team team :section :providers}]
|
||||
|
||||
@ -84,8 +84,7 @@
|
||||
(rx/mapcat (partial persist-thumbnail file-id revn))))
|
||||
|
||||
(mf/defc grid-item-thumbnail*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [can-edit file can-restore]}]
|
||||
(let [file-id (get file :id)
|
||||
revn (get file :revn)
|
||||
@ -131,7 +130,6 @@
|
||||
(deprecated-icon/icon-xref :menu (stl/css :menu-icon)))
|
||||
|
||||
(mf/defc grid-item-library*
|
||||
{::mf/props :obj}
|
||||
[{:keys [file can-restore]}]
|
||||
(mf/with-effect [file]
|
||||
(when file
|
||||
@ -467,7 +465,6 @@
|
||||
:can-restore can-restore}]])]]]]]))
|
||||
|
||||
(mf/defc grid*
|
||||
{::mf/props :obj}
|
||||
[{:keys [files project origin limit create-fn can-edit selected-files can-restore]}]
|
||||
(let [dragging? (mf/use-state false)
|
||||
project-id (get project :id)
|
||||
|
||||
@ -192,8 +192,7 @@
|
||||
(swap! state update-entry-status message))))))
|
||||
|
||||
(mf/defc import-entry*
|
||||
{::mf/props :obj
|
||||
::mf/memo true
|
||||
{::mf/memo true
|
||||
::mf/private true}
|
||||
[{:keys [entries entry edition can-be-deleted importing? on-edit on-change on-delete]}]
|
||||
(let [status (:status entry)
|
||||
|
||||
@ -27,7 +27,6 @@
|
||||
st/state))
|
||||
|
||||
(mf/defc libraries-page*
|
||||
{::mf/props :obj}
|
||||
[{:keys [team default-project]}]
|
||||
(let [files
|
||||
(mf/deref refs/shared-files)
|
||||
|
||||
@ -18,7 +18,6 @@
|
||||
(deprecated-icon/icon-xref :pin (stl/css :icon)))
|
||||
|
||||
(mf/defc pin-button*
|
||||
{::mf/props :obj}
|
||||
[{:keys [aria-label is-pinned class] :as props}]
|
||||
(let [aria-label (or aria-label (tr "dashboard.pin-unpin"))
|
||||
class (dm/str (or class "") " " (stl/css-case :button true :button-active is-pinned))
|
||||
|
||||
@ -48,7 +48,6 @@
|
||||
|
||||
(mf/defc header*
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [can-edit]}]
|
||||
(let [on-click (mf/use-fn #(st/emit! (dd/create-project)))]
|
||||
@ -62,8 +61,7 @@
|
||||
(tr "dashboard.new-project")])]))
|
||||
|
||||
(mf/defc team-hero*
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/props :obj}
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [team on-close]}]
|
||||
(let [on-nav-members-click (mf/use-fn #(st/emit! (dcm/go-to-dashboard-members)))
|
||||
|
||||
@ -102,8 +100,7 @@
|
||||
close-icon]]))
|
||||
|
||||
(mf/defc project-item*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [project is-first team files can-edit]}]
|
||||
(let [project-id (get project :id)
|
||||
team-id (get team :id)
|
||||
@ -313,7 +310,6 @@
|
||||
(l/derived :recent-files st/state))
|
||||
|
||||
(mf/defc projects-section*
|
||||
{::mf/props :obj}
|
||||
[{:keys [team projects profile]}]
|
||||
|
||||
(let [team-id (get team :id)
|
||||
|
||||
@ -32,7 +32,6 @@
|
||||
st/state))
|
||||
|
||||
(mf/defc search-page*
|
||||
{::mf/props :obj}
|
||||
[{:keys [team search-term]}]
|
||||
(let [search-term (d/nilv search-term "")
|
||||
|
||||
|
||||
@ -1123,8 +1123,7 @@
|
||||
[:div {:class (stl/css-case :separator true :overflow-separator overflow?)}]]]))
|
||||
|
||||
(mf/defc help-learning-menu*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [on-close on-click]}]
|
||||
(let [handle-click-url
|
||||
(mf/use-fn
|
||||
@ -1168,8 +1167,7 @@
|
||||
(tr "labels.give-feedback")])]))
|
||||
|
||||
(mf/defc community-contributions-menu*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [on-close]}]
|
||||
(let [handle-click-url
|
||||
(mf/use-fn
|
||||
@ -1199,8 +1197,7 @@
|
||||
(tr "labels.community")]]))
|
||||
|
||||
(mf/defc about-penpot-menu*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [on-close]}]
|
||||
(let [version cf/version
|
||||
show-release-notes
|
||||
@ -1436,8 +1433,7 @@
|
||||
nil))]))
|
||||
|
||||
(mf/defc sidebar*
|
||||
{::mf/props :obj
|
||||
::mf/wrap [mf/memo]}
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [team profile] :as props}]
|
||||
[:nav {:class (stl/css :dashboard-sidebar) :data-testid "dashboard-sidebar"}
|
||||
[:> sidebar-content* props]
|
||||
|
||||
@ -118,7 +118,6 @@
|
||||
:is-highlighted false}]))))
|
||||
|
||||
(mf/defc nitrate-sidebar*
|
||||
{::mf/props :obj}
|
||||
[{:keys [profile teams]}]
|
||||
(let [nitrate? (dnt/is-valid-license? profile)
|
||||
nitrate-license (:subscription profile)
|
||||
|
||||
@ -372,8 +372,7 @@
|
||||
(st/emit! (dtm/update-member-role params))))
|
||||
|
||||
(mf/defc team-member*
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/props :obj}
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [team member total-members profile]}]
|
||||
|
||||
(let [member-id (:id member)
|
||||
@ -501,8 +500,7 @@
|
||||
:on-leave on-leave'}]]]))
|
||||
|
||||
(mf/defc team-members*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [team profile]}]
|
||||
(let [members (get team :members)
|
||||
|
||||
@ -541,7 +539,6 @@
|
||||
:total-members total-members}])]]))
|
||||
|
||||
(mf/defc team-members-page*
|
||||
{::mf/props :obj}
|
||||
[{:keys [team profile]}]
|
||||
(mf/with-effect [team]
|
||||
(dom/set-html-title
|
||||
@ -570,7 +567,6 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(mf/defc invitation-role-selector*
|
||||
{::mf/props :obj}
|
||||
[{:keys [can-invite role status on-change]}]
|
||||
(let [show? (mf/use-state false)
|
||||
label (cond
|
||||
@ -616,8 +612,7 @@
|
||||
(tr "labels.viewer")]]]]))
|
||||
|
||||
(mf/defc invitation-actions*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [invitation team-id]}]
|
||||
(let [email (:email invitation)
|
||||
copied* (mf/use-state false)
|
||||
@ -671,8 +666,7 @@
|
||||
|
||||
(mf/defc invitation-row*
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/private true
|
||||
::mf/props :obj}
|
||||
::mf/private true}
|
||||
[{:keys [invitation can-invite team-id selected on-select-change]}]
|
||||
|
||||
(let [expired? (:expired invitation)
|
||||
@ -738,8 +732,7 @@
|
||||
:team-id team-id}])]]))
|
||||
|
||||
(mf/defc empty-invitation-table*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [can-invite team]}]
|
||||
(let
|
||||
[route (mf/deref refs/route)
|
||||
@ -879,8 +872,7 @@
|
||||
(tr accept-key)]]]]]))
|
||||
|
||||
(mf/defc invitation-section*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [team]}]
|
||||
(let [permissions (get team :permissions)
|
||||
invitations (mf/use-state (get team :invitations))
|
||||
@ -1064,7 +1056,6 @@
|
||||
:on-select-change on-select-change}])])]))
|
||||
|
||||
(mf/defc team-invitations-page*
|
||||
{::mf/props :obj}
|
||||
[{:keys [team profile]}]
|
||||
|
||||
(mf/with-effect [team]
|
||||
@ -1218,7 +1209,6 @@
|
||||
(tr "modals.create-webhook.submit-label"))}]]]]]]))
|
||||
|
||||
(mf/defc webhooks-hero*
|
||||
{::mf/props :obj}
|
||||
[]
|
||||
[:div {:class (stl/css :webhooks-hero-container)}
|
||||
[:h2 {:class (stl/css :hero-title)}
|
||||
@ -1230,8 +1220,7 @@
|
||||
(tr "dashboard.webhooks.create")]])
|
||||
|
||||
(mf/defc webhook-actions*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [on-edit on-delete can-edit]}]
|
||||
(let [show? (mf/use-state false)
|
||||
on-show (mf/use-fn #(reset! show? true))
|
||||
@ -1254,7 +1243,6 @@
|
||||
|
||||
(mf/defc webhook-item*
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [webhook permissions]}]
|
||||
(let [error-code (:error-code webhook)
|
||||
@ -1320,8 +1308,7 @@
|
||||
:can-edit can-edit}]]]))
|
||||
|
||||
(mf/defc webhooks-list*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [webhooks permissions]}]
|
||||
[:div {:class (stl/css :table-rows :webhook-table)}
|
||||
(for [webhook webhooks]
|
||||
@ -1331,7 +1318,6 @@
|
||||
:permissions permissions}])])
|
||||
|
||||
(mf/defc webhooks-page*
|
||||
{::mf/props :obj}
|
||||
[{:keys [team]}]
|
||||
(let [webhooks (:webhooks team)]
|
||||
|
||||
@ -1363,7 +1349,6 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(mf/defc team-settings-page*
|
||||
{::mf/props :obj}
|
||||
[{:keys [team]}]
|
||||
(let [nitrate? (contains? cfg/flags :nitrate)
|
||||
finput (mf/use-ref)
|
||||
|
||||
@ -64,8 +64,7 @@
|
||||
:on-finish-import on-finish}))))
|
||||
|
||||
(mf/defc title*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [on-click is-collapsed]}]
|
||||
(let [on-key-down
|
||||
(mf/use-fn
|
||||
@ -171,7 +170,6 @@
|
||||
[:div {:class (stl/css :template-link-text)} (tr "dashboard.libraries-and-templates.explore")]]]]]]))
|
||||
|
||||
(mf/defc templates-section*
|
||||
{::mf/props :obj}
|
||||
[{:keys [default-project-id profile project-id team-id]}]
|
||||
(let [templates (mf/deref builtin-templates)
|
||||
templates (mf/with-memo [templates]
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
transition: inset-block-end 300ms;
|
||||
width: calc(100% - $sz-12);
|
||||
pointer-events: none;
|
||||
z-index: var(--z-index-set);
|
||||
z-index: var(--z-index-panels);
|
||||
|
||||
&.collapsed {
|
||||
inset-block-end: calc(-1 * px2rem(228));
|
||||
|
||||
@ -45,8 +45,7 @@
|
||||
:files files}))
|
||||
|
||||
(mf/defc export-entry*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [file]}]
|
||||
[:div {:class (stl/css-case
|
||||
:file-entry true
|
||||
|
||||
@ -46,8 +46,7 @@
|
||||
(st/emit! (modal/hide)))))
|
||||
|
||||
(mf/defc modal-wrapper*
|
||||
{::mf/props :obj
|
||||
::mf/wrap [mf/memo]}
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [data]}]
|
||||
(let [wrapper-ref (mf/use-ref nil)
|
||||
components (mf/deref modal/components)
|
||||
@ -82,7 +81,6 @@
|
||||
(l/derived ::modal/modal st/state))
|
||||
|
||||
(mf/defc modal-container*
|
||||
{::mf/props :obj}
|
||||
[]
|
||||
(let [container (hooks/use-portal-container :modal)]
|
||||
(when-let [modal (mf/deref ref:modal)]
|
||||
|
||||
@ -7,16 +7,24 @@
|
||||
(ns app.main.ui.settings.options
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.config :as cf]
|
||||
[app.main.data.notifications :as ntf]
|
||||
[app.main.data.profile :as du]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.router :as rt]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.forms :as fm]
|
||||
[app.main.ui.ds.controls.switch :refer [switch*]]
|
||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
|
||||
[app.main.ui.ds.foundations.typography :as t]
|
||||
[app.main.ui.ds.foundations.typography.heading :refer [heading*]]
|
||||
[app.main.ui.ds.foundations.typography.text :refer [text*]]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.theme :as theme]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
|
||||
(def ^:private schema:options-form
|
||||
[:map {:title "OptionsForm"}
|
||||
[:lang {:optional true} [:string {:max 20}]]
|
||||
@ -76,15 +84,45 @@
|
||||
:data-testid "submit-lang-change"
|
||||
:class (stl/css :btn-primary)}]]))
|
||||
|
||||
;; --- Password Page
|
||||
(defn ^:private go-settings-feedback
|
||||
[event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (rt/nav :settings-feedback)))
|
||||
|
||||
(mf/defc webgl-settings*
|
||||
[{:keys [renderer]}]
|
||||
(let [wasm-renderer? (= renderer :wasm)
|
||||
handle-render-change
|
||||
(mf/use-fn
|
||||
(fn [enabled?]
|
||||
(st/emit! (du/update-profile-props {:renderer (if enabled? :wasm :svg)})
|
||||
(ntf/success (tr (if enabled?
|
||||
"webgl.toast.webgl-render-enabled"
|
||||
"webgl.toast.webgl-render-disabled"))))))]
|
||||
[:section {:class (stl/css :webgl-container)}
|
||||
[:header {:class (stl/css :webgl-header)}
|
||||
[:> heading* {:class (stl/css :title) :level 2 :typography t/title-large} (tr "dashboard.webgl-switch.title")]
|
||||
[:> text* {:as "span" :class (stl/css :beta) :typography t/body-small} (tr "dashboard.webgl-switch.beta")]]
|
||||
[:> text* {:class (stl/css :description) :typography t/body-medium} (tr "dashboard.webgl-switch.description")]
|
||||
[:form {:class (stl/css :webgl-form)}
|
||||
[:> heading* {:level 3 :typography t/headline-small} (tr "dashboard.webgl-switch.status")]
|
||||
[:> switch* {:label (if wasm-renderer? (tr "dashboard.webgl-switch.enabled") (tr "dashboard.webgl-switch.disabled"))
|
||||
:default-checked wasm-renderer?
|
||||
:on-change handle-render-change}]]
|
||||
[:> text* {:typography t/body-medium :class (stl/css :feedback)} [:a {:href "#" :on-click go-settings-feedback :class (stl/css :link)} (tr "dashboard.webgl-switch.feedback") [:> icon* {:icon-id "arrow-up-right" :size "s"}]]]]))
|
||||
|
||||
(mf/defc options-page
|
||||
[]
|
||||
(mf/use-effect
|
||||
#(dom/set-html-title (tr "title.settings.options")))
|
||||
(let [profile (mf/deref refs/profile)
|
||||
renderer (or (-> profile :props :renderer) :svg)]
|
||||
(mf/use-effect
|
||||
#(dom/set-html-title (tr "title.settings.options")))
|
||||
|
||||
[:div {:class (stl/css :dashboard-settings)}
|
||||
[:div {:class (stl/css :form-container) :data-testid "settings-form"}
|
||||
[:h2 (tr "labels.settings")]
|
||||
[:& options-form {}]]])
|
||||
[:div {:class (stl/css :dashboard-settings)}
|
||||
[:*
|
||||
[:div {:class (stl/css :form-container) :data-testid "settings-form"}
|
||||
[:h2 (tr "labels.settings")]
|
||||
[:& options-form {}]]
|
||||
(when (contains? cf/flags :render-switch)
|
||||
[:> webgl-settings* {:renderer renderer}])]]))
|
||||
|
||||
|
||||
@ -5,3 +5,59 @@
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@use "./profile" as *;
|
||||
@use "ds/_sizes.scss" as *;
|
||||
@use "ds/_borders.scss" as *;
|
||||
|
||||
.dashboard-settings {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
&:first-child {
|
||||
margin-block-end: var(--sp-xxxl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copied from profile.scss .form-container, but without included nested
|
||||
rules, since we want custom styles for it */
|
||||
.webgl-container {
|
||||
display: grid;
|
||||
grid-auto-rows: auto;
|
||||
gap: var(--sp-s);
|
||||
width: $sz-500;
|
||||
margin-block-start: var(--sp-xxxl);
|
||||
padding-block-start: var(--sp-xxxl);
|
||||
margin-block-end: $sz-120; /* FIXME: this should be a proper token */
|
||||
border-block-start: $b-1 solid var(--color-background-quaternary);
|
||||
color: var(--color-foreground-primary);
|
||||
}
|
||||
|
||||
.webgl-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
gap: var(--sp-m);
|
||||
}
|
||||
|
||||
.description {
|
||||
color: var(--color-foreground-secondary);
|
||||
}
|
||||
|
||||
.beta {
|
||||
color: var(--color-accent-primary);
|
||||
padding: var(--sp-xxs) var(--sp-s);
|
||||
border: $b-1 solid var(--color-accent-primary);
|
||||
border-radius: $br-4;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: var(--color-foreground-primary);
|
||||
}
|
||||
|
||||
.link {
|
||||
color: var(--color-accent-primary);
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--sp-xs);
|
||||
}
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc plan-card*
|
||||
{::mf/props :obj}
|
||||
[{:keys [card-title
|
||||
card-title-icon
|
||||
price-value price-period
|
||||
|
||||
@ -41,7 +41,6 @@
|
||||
(def TimeoutError rxjs/TimeoutError)
|
||||
|
||||
(mf/defc error-container*
|
||||
{::mf/props :obj}
|
||||
[{:keys [children]}]
|
||||
(let [profile-id (:profile-id @st/state)
|
||||
on-nav-root (mf/use-fn #(st/emit! (rt/nav-root)))]
|
||||
@ -186,7 +185,6 @@
|
||||
[:& recovery-sent-page {:email @user-email}]])]]]))
|
||||
|
||||
(mf/defc request-dialog*
|
||||
{::mf/props :obj}
|
||||
[{:keys [title content button-text on-button-click cancel-text on-close]}]
|
||||
(let [on-click (or on-button-click on-close)]
|
||||
[:div {:class (stl/css :overlay)}
|
||||
@ -532,7 +530,6 @@
|
||||
children])
|
||||
|
||||
(mf/defc exception-page*
|
||||
{::mf/props :obj}
|
||||
[{:keys [data route] :as props}]
|
||||
|
||||
(let [type (:type data)
|
||||
|
||||
@ -278,7 +278,6 @@
|
||||
:zoom zoom}])]])
|
||||
|
||||
(mf/defc viewer-content*
|
||||
{::mf/props :obj}
|
||||
[{:keys [data page-id share-id section index interactions-mode share]}]
|
||||
(let [{:keys [file users project permissions]} data
|
||||
allowed (or
|
||||
|
||||
@ -235,7 +235,6 @@
|
||||
:zoom zoom}])]]]))
|
||||
|
||||
(mf/defc comments-sidebar*
|
||||
{::mf/props :obj}
|
||||
[{:keys [profiles frame page]}]
|
||||
(let [profile (mf/deref refs/profile)
|
||||
local (mf/deref refs/comments-local)
|
||||
|
||||
@ -219,8 +219,7 @@
|
||||
:fixed? fixed?}]))
|
||||
|
||||
(mf/defc flows-menu*
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/props :obj}
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [page index]}]
|
||||
(let [flows (not-empty (:flows page))
|
||||
frames (:frames page)
|
||||
@ -268,7 +267,6 @@
|
||||
[:span {:class (stl/css :icon)} deprecated-icon/tick])])]]])))
|
||||
|
||||
(mf/defc interactions-menu*
|
||||
{::mf/props :obj}
|
||||
[{:keys [interactions-mode]}]
|
||||
(let [show-dropdown? (mf/use-state false)
|
||||
toggle-dropdown (mf/use-fn #(swap! show-dropdown? not))
|
||||
|
||||
@ -55,8 +55,7 @@
|
||||
(dom/stop-propagation event))
|
||||
|
||||
(mf/defc menu-entry*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [title shortcut on-click on-pointer-enter on-pointer-leave
|
||||
on-unmount children is-selected icon disabled value]}]
|
||||
(let [submenu-ref (mf/use-ref nil)
|
||||
@ -143,14 +142,12 @@
|
||||
children])])))
|
||||
|
||||
(mf/defc menu-separator*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[]
|
||||
[:li {:class (stl/css :separator)}])
|
||||
|
||||
(mf/defc context-menu-edit*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
(let [multiple? (> (count shapes) 1)
|
||||
|
||||
@ -252,8 +249,7 @@
|
||||
[:> menu-separator* {}]]))
|
||||
|
||||
(mf/defc context-menu-layer-position*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
(let [do-bring-forward (mf/use-fn #(st/emit! (dw/vertical-order-selected :up)))
|
||||
do-bring-to-front (mf/use-fn #(st/emit! (dw/vertical-order-selected :top)))
|
||||
@ -299,8 +295,7 @@
|
||||
[:> menu-separator* {}]]))
|
||||
|
||||
(mf/defc context-menu-flip*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[]
|
||||
(let [do-flip-vertical #(st/emit! (dw/flip-vertical-selected))
|
||||
do-flip-horizontal #(st/emit! (dw/flip-horizontal-selected))]
|
||||
@ -315,8 +310,7 @@
|
||||
[:> menu-separator* {}]]))
|
||||
|
||||
(mf/defc context-menu-thumbnail*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
(let [single? (= (count shapes) 1)
|
||||
has-frame? (some cfh/frame-shape? shapes)
|
||||
@ -332,8 +326,7 @@
|
||||
[:> menu-separator* {}]])))
|
||||
|
||||
(mf/defc context-menu-rename*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
(let [do-rename #(st/emit! (dw/start-rename-selected))]
|
||||
(when (= (count shapes) 1)
|
||||
@ -344,8 +337,7 @@
|
||||
:on-click do-rename}]])))
|
||||
|
||||
(mf/defc context-menu-group*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
(let [multiple? (> (count shapes) 1)
|
||||
single? (= (count shapes) 1)
|
||||
@ -398,8 +390,7 @@
|
||||
[:> menu-separator* {}]])]))
|
||||
|
||||
(mf/defc context-focus-mode-menu*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[]
|
||||
(let [focus (mf/deref refs/workspace-focus-selected)
|
||||
do-toggle-focus-mode #(st/emit! (dw/toggle-focus-mode))]
|
||||
@ -411,8 +402,7 @@
|
||||
:on-click do-toggle-focus-mode}]))
|
||||
|
||||
(mf/defc context-menu-path*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [shapes objects disable-flatten disable-booleans]}]
|
||||
(let [multiple? (> (count shapes) 1)
|
||||
single? (= (count shapes) 1)
|
||||
@ -489,8 +479,7 @@
|
||||
:on-click do-transform-to-path}]])])]))
|
||||
|
||||
(mf/defc context-menu-layer-options*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
(let [ids (mapv :id shapes)
|
||||
do-show-shape #(st/emit! (dw/update-shape-flags ids {:hidden false}))
|
||||
@ -515,8 +504,7 @@
|
||||
:on-click do-lock-shape}])]))
|
||||
|
||||
(mf/defc context-menu-prototype*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
(let [flows (mf/deref refs/workspace-page-flows)
|
||||
options-mode (mf/deref refs/options-mode-global)
|
||||
@ -537,8 +525,7 @@
|
||||
:on-click do-add-flow}]))))
|
||||
|
||||
(mf/defc context-menu-layout*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [shapes]}]
|
||||
(let [single? (= (count shapes) 1)
|
||||
objects (deref refs/workspace-page-objects)
|
||||
@ -667,8 +654,7 @@
|
||||
:on-click do-remove-guides}]])))
|
||||
|
||||
(mf/defc context-menu-delete*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[]
|
||||
(let [do-delete #(st/emit! (dw/delete-selected))]
|
||||
[:*
|
||||
@ -711,8 +697,7 @@
|
||||
[:> context-menu-delete* props]])))
|
||||
|
||||
(mf/defc page-item-context-menu*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [mdata]}]
|
||||
(let [page (:page mdata)
|
||||
deletable? (:deletable? mdata)
|
||||
@ -739,7 +724,6 @@
|
||||
:on-click do-duplicate}]]))
|
||||
|
||||
(mf/defc viewport-context-menu*
|
||||
{::mf/props :obj}
|
||||
[]
|
||||
(let [focus (mf/deref refs/workspace-focus-selected)
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
@ -762,8 +746,7 @@
|
||||
:on-click do-toggle-focus-mode}])]))
|
||||
|
||||
(mf/defc grid-track-context-menu*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [mdata]}]
|
||||
(let [{:keys [type index grid-id]} mdata
|
||||
do-delete-track
|
||||
@ -812,8 +795,7 @@
|
||||
[:> menu-entry* {:title (tr "workspace.context-menu.grid-track.row.delete-shapes") :on-click do-delete-track-shapes}]])))
|
||||
|
||||
(mf/defc grid-cells-context-menu*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [mdata]}]
|
||||
(let [{:keys [grid cells]} mdata
|
||||
|
||||
|
||||
@ -107,8 +107,7 @@
|
||||
"\u00A0")))
|
||||
|
||||
(mf/defc library-description*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [summary]}]
|
||||
(let [components-count (get summary :components)
|
||||
graphics-count (get summary :graphics)
|
||||
@ -133,8 +132,7 @@
|
||||
(tr "workspace.libraries.typography" (c typography-count))])]))
|
||||
|
||||
(mf/defc sample-library-entry*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [library importing]}]
|
||||
(let [id (:id library)
|
||||
importing? (deref importing)
|
||||
@ -185,8 +183,7 @@
|
||||
(not (ctob/empty-lib? tokens-lib))))
|
||||
|
||||
(mf/defc libraries-tab*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [is-shared linked-libraries shared-libraries]}]
|
||||
(let [file-id (mf/use-ctx ctx/current-file-id)
|
||||
search-term* (mf/use-state "")
|
||||
@ -485,8 +482,7 @@
|
||||
:typographies typographies}]))
|
||||
|
||||
(mf/defc updates-tab*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [file-id libraries]}]
|
||||
;; FIXME: naming
|
||||
(let [summary?* (mf/use-state true)
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
[app.main.data.exports.assets :as de]
|
||||
[app.main.data.exports.files :as fexp]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.notifications :as ntf]
|
||||
[app.main.data.plugins :as dp]
|
||||
[app.main.data.profile :as du]
|
||||
[app.main.data.shortcuts :as scd]
|
||||
@ -226,8 +227,10 @@
|
||||
(mf/defc preferences-menu*
|
||||
{::mf/private true
|
||||
::mf/wrap [mf/memo]}
|
||||
[{:keys [layout profile toggle-flag on-close toggle-theme]}]
|
||||
(let [show-nudge-options
|
||||
[{:keys [layout profile toggle-flag on-close toggle-theme toggle-render]}]
|
||||
(let [renderer (or (-> profile :props :renderer) :svg)
|
||||
|
||||
show-nudge-options
|
||||
(mf/use-fn
|
||||
#(modal/show! {:type :nudge-option}))]
|
||||
|
||||
@ -321,7 +324,17 @@
|
||||
"light" (tr "workspace.header.menu.toggle-system-theme")
|
||||
"system" (tr "workspace.header.menu.toggle-dark-theme")
|
||||
(tr "workspace.header.menu.toggle-light-theme"))]
|
||||
[:> shortcuts* {:id :toggle-theme}]]]))
|
||||
[:> shortcuts* {:id :toggle-theme}]]
|
||||
(when (contains? cf/flags :render-switch)
|
||||
[:> dropdown-menu-item* {:on-click toggle-render
|
||||
:class (stl/css :base-menu-item :submenu-item)
|
||||
:on-key-down (fn [event]
|
||||
(when (kbd/enter? event)
|
||||
(toggle-render event)))}
|
||||
[:span {:class (stl/css :item-name)}
|
||||
(if (= renderer :wasm)
|
||||
(tr "workspace.header.menu.disable-webgl")
|
||||
(tr "workspace.header.menu.enable-webgl"))]])]))
|
||||
|
||||
(mf/defc view-menu*
|
||||
{::mf/private true
|
||||
@ -920,6 +933,18 @@
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (du/toggle-theme))))
|
||||
|
||||
toggle-render
|
||||
(mf/use-fn
|
||||
(mf/deps profile)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [renderer (or (-> profile :props :renderer) :svg)
|
||||
next-renderer (if (= renderer :wasm) :svg :wasm)]
|
||||
(st/emit! (du/update-profile-props {:renderer next-renderer})
|
||||
(ntf/success (tr (if (= next-renderer :wasm)
|
||||
"webgl.toast.webgl-render-enabled"
|
||||
"webgl.toast.webgl-render-disabled")))))))
|
||||
|
||||
open-plugins-manager
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
@ -1099,6 +1124,7 @@
|
||||
:profile profile
|
||||
:toggle-flag toggle-flag
|
||||
:toggle-theme toggle-theme
|
||||
:toggle-render toggle-render
|
||||
:on-close close-sub-menu}]
|
||||
|
||||
:plugins
|
||||
|
||||
@ -418,9 +418,10 @@
|
||||
(cond-> #js {:pointerEvents "all"}
|
||||
render-wasm?
|
||||
(obj/merge!
|
||||
#js {"--editor-container-width" (dm/str width "px")
|
||||
"--editor-container-height" (dm/str height "px")
|
||||
"--fallback-families" (if (seq fallback-families) (dm/str (str/join ", " fallback-families)) "sourcesanspro")})
|
||||
#js {"--editor-container-width" "auto"
|
||||
"--editor-container-height" "auto"
|
||||
"--fallback-families" (if (seq fallback-families) (dm/str (str/join ", " fallback-families)) "sourcesanspro")
|
||||
:display "flex"})
|
||||
|
||||
(not render-wasm?)
|
||||
(obj/merge!
|
||||
|
||||
@ -29,7 +29,6 @@
|
||||
|
||||
(mf/defc assets-libraries*
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [filters]}]
|
||||
(let [file-id (mf/use-ctx ctx/current-file-id)
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc token-settings*
|
||||
{::mf/wrap-props false}
|
||||
[]
|
||||
(let [file-data (deref refs/workspace-data)
|
||||
base-font-size* (mf/use-state #(ctf/get-base-font-size file-data))
|
||||
|
||||
@ -448,7 +448,6 @@
|
||||
:fill "var(--app-white)"}]))]))
|
||||
|
||||
(mf/defc gradient-handlers-impl*
|
||||
{::mf/props :obj}
|
||||
[{:keys [zoom stops gradient editing shape]}]
|
||||
(let [transform (gsh/transform-matrix shape)
|
||||
transform-inverse (gsh/inverse-transform-matrix shape)
|
||||
@ -517,8 +516,7 @@
|
||||
:on-change-width on-change-width}]))
|
||||
|
||||
(mf/defc gradient-handlers*
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/props :obj}
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [id zoom]}]
|
||||
(let [shape-ref (mf/use-memo (mf/deps id) #(refs/object-by-id id))
|
||||
shape (mf/deref shape-ref)
|
||||
|
||||
@ -370,7 +370,7 @@
|
||||
:else
|
||||
(show-unavailable)))))]
|
||||
(reset! canvas-init? false)
|
||||
(->> wasm.api/module
|
||||
(->> @wasm.api/module
|
||||
(p/fmap (fn [ready?]
|
||||
(when ready?
|
||||
(try-init 3)))))
|
||||
@ -378,6 +378,7 @@
|
||||
(vreset! unmounted? true)
|
||||
(when-let [timeout-id @timeout-id-ref]
|
||||
(js/clearTimeout timeout-id))
|
||||
(wasm.api/end-page-transition!)
|
||||
(wasm.api/clear-canvas)))))
|
||||
|
||||
(mf/with-effect [show-text-editor? workspace-editor-state edition]
|
||||
|
||||
@ -1077,16 +1077,18 @@
|
||||
|
||||
(defn intersect-position-in-shape
|
||||
[id position]
|
||||
(let [buffer (uuid/get-u32 id)
|
||||
result
|
||||
(h/call wasm/internal-module "_intersect_position_in_shape"
|
||||
(aget buffer 0)
|
||||
(aget buffer 1)
|
||||
(aget buffer 2)
|
||||
(aget buffer 3)
|
||||
(:x position)
|
||||
(:y position))]
|
||||
(= result 1)))
|
||||
(if (and wasm/context-initialized? (not @wasm/context-lost?))
|
||||
(let [buffer (uuid/get-u32 id)
|
||||
result
|
||||
(h/call wasm/internal-module "_intersect_position_in_shape"
|
||||
(aget buffer 0)
|
||||
(aget buffer 1)
|
||||
(aget buffer 2)
|
||||
(aget buffer 3)
|
||||
(:x position)
|
||||
(:y position))]
|
||||
(= result 1))
|
||||
false))
|
||||
|
||||
(def render-finish
|
||||
(letfn [(do-render []
|
||||
|
||||
@ -1216,6 +1216,27 @@ msgstr "Type to search results"
|
||||
msgid "dashboard.unpublish-shared"
|
||||
msgstr "Unpublish Library"
|
||||
|
||||
msgid "dashboard.webgl-switch.title"
|
||||
msgstr "WebGL rendering"
|
||||
|
||||
msgid "dashboard.webgl-switch.beta"
|
||||
msgstr "Beta"
|
||||
|
||||
msgid "dashboard.webgl-switch.description"
|
||||
msgstr "WebGL rendering can improve performance, but it is in beta and may be less stable. Some visual differences may appear between the canvas, exports (SVG/PDF), and view mode."
|
||||
|
||||
msgid "dashboard.webgl-switch.status"
|
||||
msgstr "Status"
|
||||
|
||||
msgid "dashboard.webgl-switch.enabled"
|
||||
msgstr "Enabled"
|
||||
|
||||
msgid "dashboard.webgl-switch.disabled"
|
||||
msgstr "Disabled"
|
||||
|
||||
msgid "dashboard.webgl-switch.feedback"
|
||||
msgstr "Give feedback"
|
||||
|
||||
#:src/app/main/ui/workspace/tokens/import_from_library.cljs
|
||||
msgid "modals.import-library-tokens.title"
|
||||
msgstr "Import tokens from library?"
|
||||
@ -5995,6 +6016,12 @@ msgstr "Switch to light theme"
|
||||
msgid "workspace.header.menu.toggle-system-theme"
|
||||
msgstr "Switch to system theme"
|
||||
|
||||
msgid "workspace.header.menu.enable-webgl"
|
||||
msgstr "Enable WebGL rendering (beta)"
|
||||
|
||||
msgid "workspace.header.menu.disable-webgl"
|
||||
msgstr "Disable WebGL rendering (beta)"
|
||||
|
||||
#: src/app/main/ui/workspace/main_menu.cljs:492
|
||||
msgid "workspace.header.menu.undo"
|
||||
msgstr "Undo"
|
||||
@ -9196,6 +9223,12 @@ msgstr "Projects and files will remain available to team members, but the organi
|
||||
msgid "modals.remove-team-org.accept"
|
||||
msgstr "Remove from organization"
|
||||
|
||||
msgid "webgl.toast.webgl-render-enabled"
|
||||
msgstr "WebGL rendering enabled"
|
||||
|
||||
msgid "webgl.toast.webgl-render-disabled"
|
||||
msgstr "WebGL rendering disabled"
|
||||
|
||||
#, unused
|
||||
msgid "workspace.viewport.click-to-close-path"
|
||||
msgstr "Click to close the path"
|
||||
|
||||
@ -1291,6 +1291,27 @@ msgstr "Tu nombre"
|
||||
msgid "dashboard.your-penpot"
|
||||
msgstr "Tu Penpot"
|
||||
|
||||
msgid "dashboard.webgl-switch.title"
|
||||
msgstr "Renderizado WebGL"
|
||||
|
||||
msgid "dashboard.webgl-switch.beta"
|
||||
msgstr "Beta"
|
||||
|
||||
msgid "dashboard.webgl-switch.description"
|
||||
msgstr "El renderizado WebGL puede mejorar el rendimiento, pero está en beta y puede ser menos estable. Pueden aparecer diferencias visuales entre el lienzo, las exportaciones (SVG/PDF) y el modo de vista."
|
||||
|
||||
msgid "dashboard.webgl-switch.status"
|
||||
msgstr "Estado"
|
||||
|
||||
msgid "dashboard.webgl-switch.enabled"
|
||||
msgstr "Activado"
|
||||
|
||||
msgid "dashboard.webgl-switch.disabled"
|
||||
msgstr "Desactivado"
|
||||
|
||||
msgid "dashboard.webgl-switch.feedback"
|
||||
msgstr "Enviar comentarios"
|
||||
|
||||
#: src/app/main/ui/alert.cljs:35
|
||||
msgid "ds.alert-ok"
|
||||
msgstr "Ok"
|
||||
@ -5906,6 +5927,13 @@ msgstr "Cambiar a tema claro"
|
||||
msgid "workspace.header.menu.toggle-system-theme"
|
||||
msgstr "Cambiar a tema del sistema"
|
||||
|
||||
msgid "workspace.header.menu.enable-webgl"
|
||||
msgstr "Activar renderizado WebGL (beta)"
|
||||
|
||||
msgid "workspace.header.menu.disable-webgl"
|
||||
msgstr "Desactivar renderizado WebGL (beta)"
|
||||
|
||||
|
||||
#: src/app/main/ui/workspace/main_menu.cljs:492
|
||||
msgid "workspace.header.menu.undo"
|
||||
msgstr "Deshacer"
|
||||
@ -8937,6 +8965,12 @@ msgstr "Los proyectos y archivos seguirán estando disponibles para los miembros
|
||||
msgid "modals.remove-team-org.accept"
|
||||
msgstr "Eliminar de la organización"
|
||||
|
||||
msgid "webgl.toast.webgl-render-enabled"
|
||||
msgstr "Renderizado WebGL activado"
|
||||
|
||||
msgid "webgl.toast.webgl-render-disabled"
|
||||
msgstr "Renderizado WebGL desactivado"
|
||||
|
||||
#, unused
|
||||
msgid "workspace.viewport.click-to-close-path"
|
||||
msgstr "Pulsar para cerrar la ruta"
|
||||
|
||||
@ -16,9 +16,9 @@
|
||||
"fmt": "./scripts/fmt"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@github/copilot": "^1.0.35",
|
||||
"@github/copilot": "^1.0.36",
|
||||
"@types/node": "^25.6.0",
|
||||
"esbuild": "^0.28.0",
|
||||
"opencode-ai": "^1.14.22"
|
||||
"opencode-ai": "^1.14.28"
|
||||
}
|
||||
}
|
||||
|
||||
164
pnpm-lock.yaml
generated
164
pnpm-lock.yaml
generated
@ -9,8 +9,8 @@ importers:
|
||||
.:
|
||||
devDependencies:
|
||||
'@github/copilot':
|
||||
specifier: ^1.0.35
|
||||
version: 1.0.35
|
||||
specifier: ^1.0.36
|
||||
version: 1.0.36
|
||||
'@types/node':
|
||||
specifier: ^25.6.0
|
||||
version: 25.6.0
|
||||
@ -18,8 +18,8 @@ importers:
|
||||
specifier: ^0.28.0
|
||||
version: 0.28.0
|
||||
opencode-ai:
|
||||
specifier: ^1.14.22
|
||||
version: 1.14.22
|
||||
specifier: ^1.14.28
|
||||
version: 1.14.28
|
||||
|
||||
packages:
|
||||
|
||||
@ -179,44 +179,44 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@github/copilot-darwin-arm64@1.0.35':
|
||||
resolution: {integrity: sha512-NNZE0TOz0HOlv7eqlh6EcQbNkhtnIHReBLieW6pfDUUTKkgsqbUu1MOitF8m+LUQk3ml1T0MQ5MOfad1HSa/MQ==}
|
||||
'@github/copilot-darwin-arm64@1.0.36':
|
||||
resolution: {integrity: sha512-5qkb7frTS4K/LdTDLrzKo78VR4aw/EZ6JzLz4KfmaW4UYyPiNirExDFXa/By22X0o8YMfOp4MCA2KSCAxKdgTg==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
hasBin: true
|
||||
|
||||
'@github/copilot-darwin-x64@1.0.35':
|
||||
resolution: {integrity: sha512-XCv/mfdv0rnrtrNVOluio/N/kyCge0uG2hghvtlgO/+z6EjvzFygkpXXS1gVxiXhWc3lX232cTXQU3zklC/8Ng==}
|
||||
'@github/copilot-darwin-x64@1.0.36':
|
||||
resolution: {integrity: sha512-AdsM8QtM5QSzMLpavLREh8HALO5G+VWzGNQqIHu4f0YQC/s1cGoiwo3wsgkpxRcLGBykFc+bDX3yK3MDQ8XvSw==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
hasBin: true
|
||||
|
||||
'@github/copilot-linux-arm64@1.0.35':
|
||||
resolution: {integrity: sha512-mbaadATfJPzmXq2SD1TWocIG/GobcYC6OvNFhCG8UXMsiXY5cevhszl5ujuayhPJBxS77Yj5uvIFjNQ1Kf5V8Q==}
|
||||
'@github/copilot-linux-arm64@1.0.36':
|
||||
resolution: {integrity: sha512-n7K1I6r0ggOJ4A9uAMS11USTvn6BKtAwvrOkzEaeRK89VNUJzpTe6p0mE13ItzRe5eot9WLBQOxvXLtL9f6E+g==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
hasBin: true
|
||||
|
||||
'@github/copilot-linux-x64@1.0.35':
|
||||
resolution: {integrity: sha512-NrZ0VjztdBbJ5qAmuUtuKsWkimOaqzjDV+ZGUv1FxSxoys40kiiakQ5WbnMFDzaIFaf47zDi++6ixgQzq7Jk5A==}
|
||||
'@github/copilot-linux-x64@1.0.36':
|
||||
resolution: {integrity: sha512-wBtCdR3ITZcq07BJbkwHfwI6ayiwbH5pF1ex+Ycl4UI+Lf1vP9eQD6wJppPgsrjwFcdeWRThaYTPCRTkSGHv5g==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
hasBin: true
|
||||
|
||||
'@github/copilot-win32-arm64@1.0.35':
|
||||
resolution: {integrity: sha512-KQN7Q7+oPyglmvUEiMp6SYWjl30VSu91T0dUpNHbUs/xRM3qgnCymLPPUyBZGWHog/FueUAsRkhisMHWQVnO+g==}
|
||||
'@github/copilot-win32-arm64@1.0.36':
|
||||
resolution: {integrity: sha512-0GzZUZQn07alI8BgbzK0NlR5+ta/Rd0sWmd8kbRCns7oybAIkSALy6BKVwJmVHtXUi6h4iUE8oiFhkn0spymvw==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
hasBin: true
|
||||
|
||||
'@github/copilot-win32-x64@1.0.35':
|
||||
resolution: {integrity: sha512-J0XhXO2FmlFr8pGa970xEd4tr1rqFiZxoaPW5WvkJYZoZUHbBhFcGasp5/yEeJ71b3vI4PHm/mSZZebD3ALMKQ==}
|
||||
'@github/copilot-win32-x64@1.0.36':
|
||||
resolution: {integrity: sha512-UBX9qj0McCK/SLq93XIr1i80fj3b3XmE3befVFrzxQuTeOoxLURN35vi7W+4x+4ZfsDHQpRTlJNjZw9w0fPr+Q==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
hasBin: true
|
||||
|
||||
'@github/copilot@1.0.35':
|
||||
resolution: {integrity: sha512-O1nUy8DXOTE+v86b/FTkyu09EMrDy+vj+2rhmUOcmsXGe0RE5ECyESsasUTUoHK/CSgAExFTziNxbubUoiMMfg==}
|
||||
'@github/copilot@1.0.36':
|
||||
resolution: {integrity: sha512-x0N5wLzw+tANzb+vCFYLHn3BV3qii2oyn14wC20RO7SsS8/YeBH8olvwlDLJ4PB0mL17QOiytNCdkvjvprm28w==}
|
||||
hasBin: true
|
||||
|
||||
'@types/node@25.6.0':
|
||||
@ -227,67 +227,67 @@ packages:
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
opencode-ai@1.14.22:
|
||||
resolution: {integrity: sha512-J+q1Ehlfg7SSXw2aIY8Mb47FHhPTN8IciKNt0/D+H/brO8RWLe67WjFzxhh/z9SSad9wPcCiLRGAc/iAn8W8wA==}
|
||||
opencode-ai@1.14.28:
|
||||
resolution: {integrity: sha512-ZPukJNvujSVa+LVoXvj2ciUV57UcnuxmMtzpFQBYd6fbhjeT1vMC6jCurO/5mIp76fiPmGM7ilzRXVeY6bIwPw==}
|
||||
hasBin: true
|
||||
|
||||
opencode-darwin-arm64@1.14.22:
|
||||
resolution: {integrity: sha512-h9FjzNoDRsuJD0EEg535P9ul5TyrWovwx591VmuG8fp9d4PoSrAN1O3Zi07GJjkrYyrB8g3c+x5whDqJCz+qog==}
|
||||
opencode-darwin-arm64@1.14.28:
|
||||
resolution: {integrity: sha512-Gu2vZYACAeoewfPhgJDAaScwRo1K5YZq7tVpPKw2rpul34OpOPLk4oB4Pmr539iWiagK+DLuUxnbJIbRRYCS5g==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
opencode-darwin-x64-baseline@1.14.22:
|
||||
resolution: {integrity: sha512-GgfP0wSm9/I+j3shOxfeA++7yZpXS6Y1Vis258nEFoRS9Xfv3YlHom7c/8BR9rYqeUE/+rrijP7PrGWGl+IHBw==}
|
||||
opencode-darwin-x64-baseline@1.14.28:
|
||||
resolution: {integrity: sha512-/KsZkZh5oh6urHWwIHJudS6sedBil59E/4o7/7TuxPy/pOdRlSlSWVkMJd20AmqM4G/qILF/GthXy3D2+f99Tg==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
opencode-darwin-x64@1.14.22:
|
||||
resolution: {integrity: sha512-cyKRo22sxDwu4ITOlENwXaqVM9kMGndwSaAd95gz1Rmz5NYMShUO/8eckrD2MhS2wm+QvKw9XkRVWVHWQlZw3Q==}
|
||||
opencode-darwin-x64@1.14.28:
|
||||
resolution: {integrity: sha512-D6BnAXlSdQDRtZgAg6OxWT6CEzbbONnlYof9hdPbaIIaNyBLjqK+Er2O1rrbiXFhSbs7YHBiDoGd+nNUymx4Ng==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
opencode-linux-arm64-musl@1.14.22:
|
||||
resolution: {integrity: sha512-DtSd5tbGk6R5+hGhqViSvbY8ICf+u4oVQhfvCAplQCb1UEwYVc0+oAF6PimFJ+o8i8L6x14O0rry0NaRzZ0CzA==}
|
||||
opencode-linux-arm64-musl@1.14.28:
|
||||
resolution: {integrity: sha512-7R1GHqSg/UuT9r77GF2skh8r66WkZcphmDWAWaV2dmptJlxEJeV9I2jbE2i8Ctp4BzPUexFqfSoBA82S9Dcf+A==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
opencode-linux-arm64@1.14.22:
|
||||
resolution: {integrity: sha512-ohK4LkkGvzB4ptr0nqDOVi2JEJMLROfy1s2U2A4Qrh+1Y0QimgH2b5VgTm+BjA3bC2Hm8Yf/IfkitqlUnCp7YA==}
|
||||
opencode-linux-arm64@1.14.28:
|
||||
resolution: {integrity: sha512-jdTrs4YpPGFGZOMLuiaSfOUzkjAA+lnIEaW6HYLvaey3WsBnu3S4utaBhXURincp20H1JPQcahDOe+jjGZH7xw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
opencode-linux-x64-baseline-musl@1.14.22:
|
||||
resolution: {integrity: sha512-oZffotEbGXbA38Y0Dmj7IVq0ATl3nKbP8j91Z0zR5kBEBykOqExJIyc9pZpModgfPf86k98XBsRHiVLK4u9ARw==}
|
||||
opencode-linux-x64-baseline-musl@1.14.28:
|
||||
resolution: {integrity: sha512-GKxZXj8/Mbutfs1DW4v0/rEWcAQrD/RUI9kV9VhMoNA8vUt0nuA3H9UvbFXh9EJj2C+RBSPLlMGal++oCH4c4w==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
opencode-linux-x64-baseline@1.14.22:
|
||||
resolution: {integrity: sha512-J67YAIWr3E03o9e6wNaPEqBo+9FcPKf5CzjIUSb8yNDyobWON1HHihcuu0hCJ6wF9J9awmlp2/4mO1HOoCo3QQ==}
|
||||
opencode-linux-x64-baseline@1.14.28:
|
||||
resolution: {integrity: sha512-Dtl+xjEAKaWNk2l3iC9ebwi79BkChHIdtx97ksZKTLjAeR424Zh3vnjuWjpMYk9YAnesVlwL8y4kHs2Y736Zpw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
opencode-linux-x64-musl@1.14.22:
|
||||
resolution: {integrity: sha512-r+QnqwR/OPmMm197Kb8VLD9mkZGFXz4m5QCZFxOAL34k8AhQZqn3d2mx2bfrMBVfoSiSVxa3jEjZEbNNFGlICQ==}
|
||||
opencode-linux-x64-musl@1.14.28:
|
||||
resolution: {integrity: sha512-XyzWl35L8N6El/hxAM28bDUHLCY0aujMtprDTCYXVckeNxBkN3idM4EfdLtJaUHkE6bqMr+m6wXQl4oYDoOtpg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
opencode-linux-x64@1.14.22:
|
||||
resolution: {integrity: sha512-MSUaO/Cvfb8DFRYETVrVeCnKtoIfgLflyB+O8xQOkVtjMKJ41M+1dFSMyZ3LQa2Vfp5tDskyMhj7eUxvT/owgQ==}
|
||||
opencode-linux-x64@1.14.28:
|
||||
resolution: {integrity: sha512-XnpQrud15bvUBvOI58tOGUBTrwqKHl6bYQ3eoy5HhGa2spUnRv3B/HU8QiS6QuNbmkPxRPR+vuTGtBYQvtRGPw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
opencode-windows-arm64@1.14.22:
|
||||
resolution: {integrity: sha512-8grcxLSf9BD9Bt38MIxXfkI6aOFophVgM0US5r8nAUdVU78/8TS9Flnn6D39GM5RmxzqGWMl1u10vMFrBtMwPA==}
|
||||
opencode-windows-arm64@1.14.28:
|
||||
resolution: {integrity: sha512-emR1oEoLe6soASahJNX6IwR9x8rJkbwBXDnXNTWQcGdSxKBMD4/cLkq84k/5zqLfB7dbUChTw7eFz7u8Sa5VQw==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
opencode-windows-x64-baseline@1.14.22:
|
||||
resolution: {integrity: sha512-R/o36LpmQmbv/tL2pkcmApn6030z/1oJIYmjDkW5a4K5MXmV7aq+jWrH5p6iYKp9fo9L8oCtOp/rELMBqDS3UA==}
|
||||
opencode-windows-x64-baseline@1.14.28:
|
||||
resolution: {integrity: sha512-ARKHTThHezib44QPLiivYI8c71iNE9iNDubwV5XxUhM2FtzMJkZGma+EgbcCsXwY5r0lAsarzzDMqYB0YfCZ1A==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
opencode-windows-x64@1.14.22:
|
||||
resolution: {integrity: sha512-jVbZ4VA5b5MF2QhWQOE1VYBKdBE0v/ZebFjwzs6Vieazfgr6OFnGSHVP5WJbU/r6zDssbTBzzpnFxo0IY1SQWw==}
|
||||
opencode-windows-x64@1.14.28:
|
||||
resolution: {integrity: sha512-tEpblIEdmlJ7npo5Bq+1O7uup9jCOyqnnA63t+3JQiNQ1et3UTjNb5ruAjb7sudUer6i5MlQCwNXBjitjuU4Kg==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
@ -374,32 +374,32 @@ snapshots:
|
||||
'@esbuild/win32-x64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@github/copilot-darwin-arm64@1.0.35':
|
||||
'@github/copilot-darwin-arm64@1.0.36':
|
||||
optional: true
|
||||
|
||||
'@github/copilot-darwin-x64@1.0.35':
|
||||
'@github/copilot-darwin-x64@1.0.36':
|
||||
optional: true
|
||||
|
||||
'@github/copilot-linux-arm64@1.0.35':
|
||||
'@github/copilot-linux-arm64@1.0.36':
|
||||
optional: true
|
||||
|
||||
'@github/copilot-linux-x64@1.0.35':
|
||||
'@github/copilot-linux-x64@1.0.36':
|
||||
optional: true
|
||||
|
||||
'@github/copilot-win32-arm64@1.0.35':
|
||||
'@github/copilot-win32-arm64@1.0.36':
|
||||
optional: true
|
||||
|
||||
'@github/copilot-win32-x64@1.0.35':
|
||||
'@github/copilot-win32-x64@1.0.36':
|
||||
optional: true
|
||||
|
||||
'@github/copilot@1.0.35':
|
||||
'@github/copilot@1.0.36':
|
||||
optionalDependencies:
|
||||
'@github/copilot-darwin-arm64': 1.0.35
|
||||
'@github/copilot-darwin-x64': 1.0.35
|
||||
'@github/copilot-linux-arm64': 1.0.35
|
||||
'@github/copilot-linux-x64': 1.0.35
|
||||
'@github/copilot-win32-arm64': 1.0.35
|
||||
'@github/copilot-win32-x64': 1.0.35
|
||||
'@github/copilot-darwin-arm64': 1.0.36
|
||||
'@github/copilot-darwin-x64': 1.0.36
|
||||
'@github/copilot-linux-arm64': 1.0.36
|
||||
'@github/copilot-linux-x64': 1.0.36
|
||||
'@github/copilot-win32-arm64': 1.0.36
|
||||
'@github/copilot-win32-x64': 1.0.36
|
||||
|
||||
'@types/node@25.6.0':
|
||||
dependencies:
|
||||
@ -434,55 +434,55 @@ snapshots:
|
||||
'@esbuild/win32-ia32': 0.28.0
|
||||
'@esbuild/win32-x64': 0.28.0
|
||||
|
||||
opencode-ai@1.14.22:
|
||||
opencode-ai@1.14.28:
|
||||
optionalDependencies:
|
||||
opencode-darwin-arm64: 1.14.22
|
||||
opencode-darwin-x64: 1.14.22
|
||||
opencode-darwin-x64-baseline: 1.14.22
|
||||
opencode-linux-arm64: 1.14.22
|
||||
opencode-linux-arm64-musl: 1.14.22
|
||||
opencode-linux-x64: 1.14.22
|
||||
opencode-linux-x64-baseline: 1.14.22
|
||||
opencode-linux-x64-baseline-musl: 1.14.22
|
||||
opencode-linux-x64-musl: 1.14.22
|
||||
opencode-windows-arm64: 1.14.22
|
||||
opencode-windows-x64: 1.14.22
|
||||
opencode-windows-x64-baseline: 1.14.22
|
||||
opencode-darwin-arm64: 1.14.28
|
||||
opencode-darwin-x64: 1.14.28
|
||||
opencode-darwin-x64-baseline: 1.14.28
|
||||
opencode-linux-arm64: 1.14.28
|
||||
opencode-linux-arm64-musl: 1.14.28
|
||||
opencode-linux-x64: 1.14.28
|
||||
opencode-linux-x64-baseline: 1.14.28
|
||||
opencode-linux-x64-baseline-musl: 1.14.28
|
||||
opencode-linux-x64-musl: 1.14.28
|
||||
opencode-windows-arm64: 1.14.28
|
||||
opencode-windows-x64: 1.14.28
|
||||
opencode-windows-x64-baseline: 1.14.28
|
||||
|
||||
opencode-darwin-arm64@1.14.22:
|
||||
opencode-darwin-arm64@1.14.28:
|
||||
optional: true
|
||||
|
||||
opencode-darwin-x64-baseline@1.14.22:
|
||||
opencode-darwin-x64-baseline@1.14.28:
|
||||
optional: true
|
||||
|
||||
opencode-darwin-x64@1.14.22:
|
||||
opencode-darwin-x64@1.14.28:
|
||||
optional: true
|
||||
|
||||
opencode-linux-arm64-musl@1.14.22:
|
||||
opencode-linux-arm64-musl@1.14.28:
|
||||
optional: true
|
||||
|
||||
opencode-linux-arm64@1.14.22:
|
||||
opencode-linux-arm64@1.14.28:
|
||||
optional: true
|
||||
|
||||
opencode-linux-x64-baseline-musl@1.14.22:
|
||||
opencode-linux-x64-baseline-musl@1.14.28:
|
||||
optional: true
|
||||
|
||||
opencode-linux-x64-baseline@1.14.22:
|
||||
opencode-linux-x64-baseline@1.14.28:
|
||||
optional: true
|
||||
|
||||
opencode-linux-x64-musl@1.14.22:
|
||||
opencode-linux-x64-musl@1.14.28:
|
||||
optional: true
|
||||
|
||||
opencode-linux-x64@1.14.22:
|
||||
opencode-linux-x64@1.14.28:
|
||||
optional: true
|
||||
|
||||
opencode-windows-arm64@1.14.22:
|
||||
opencode-windows-arm64@1.14.28:
|
||||
optional: true
|
||||
|
||||
opencode-windows-x64-baseline@1.14.22:
|
||||
opencode-windows-x64-baseline@1.14.28:
|
||||
optional: true
|
||||
|
||||
opencode-windows-x64@1.14.22:
|
||||
opencode-windows-x64@1.14.28:
|
||||
optional: true
|
||||
|
||||
undici-types@7.19.2: {}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user