mirror of
https://github.com/penpot/penpot.git
synced 2026-08-01 19:06:18 +00:00
Merge remote-tracking branch 'refs/remotes/origin/develop' into develop
This commit is contained in:
commit
44c15480f2
@ -11,6 +11,7 @@
|
|||||||
[app.common.types.shape.layout :as ctl]
|
[app.common.types.shape.layout :as ctl]
|
||||||
[app.main.data.helpers :as dsh]
|
[app.main.data.helpers :as dsh]
|
||||||
[app.main.data.workspace.viewport-wasm :as dwvw]
|
[app.main.data.workspace.viewport-wasm :as dwvw]
|
||||||
|
[app.main.streams :as ms]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
(defn hover-grid-cell
|
(defn hover-grid-cell
|
||||||
@ -88,7 +89,11 @@
|
|||||||
(ptk/reify ::stop-grid-layout-editing
|
(ptk/reify ::stop-grid-layout-editing
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(update state :workspace-grid-edition dissoc grid-id))))
|
(update state :workspace-grid-edition dissoc grid-id))
|
||||||
|
|
||||||
|
ptk/EffectEvent
|
||||||
|
(effect [_ _ _]
|
||||||
|
(ms/clear-transform-preview!))))
|
||||||
|
|
||||||
(defn locate-board
|
(defn locate-board
|
||||||
[grid-id]
|
[grid-id]
|
||||||
|
|||||||
@ -143,8 +143,7 @@
|
|||||||
|
|
||||||
ptk/EffectEvent
|
ptk/EffectEvent
|
||||||
(effect [_ _ _]
|
(effect [_ _ _]
|
||||||
(rx/push! ms/wasm-modifiers nil)
|
(ms/clear-transform-preview!))))
|
||||||
(rx/push! ms/workspace-selrect nil))))
|
|
||||||
|
|
||||||
;; -- Resize --------------------------------------------------------
|
;; -- Resize --------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@ -32,6 +32,17 @@
|
|||||||
(defonce workspace-selrect
|
(defonce workspace-selrect
|
||||||
(rx/behavior-subject nil))
|
(rx/behavior-subject nil))
|
||||||
|
|
||||||
|
(defn clear-transform-preview!
|
||||||
|
"Reset the interactive-transform preview behaviour-subjects. Controls
|
||||||
|
that drive a live preview (drag/resize/rotate, flex spacing handles,
|
||||||
|
grid track/cell gestures) set these via `set-wasm-modifiers` and clear
|
||||||
|
them at gesture end. If the control unmounts mid-gesture that clearing
|
||||||
|
never runs, so the stale selrect keeps displacing the DOM selection
|
||||||
|
overlay of the next selection. Call from gesture end / unmount cleanup."
|
||||||
|
[]
|
||||||
|
(rx/push! wasm-modifiers nil)
|
||||||
|
(rx/push! workspace-selrect nil))
|
||||||
|
|
||||||
;; --- Derived streams
|
;; --- Derived streams
|
||||||
|
|
||||||
(defonce ^:private pointer
|
(defonce ^:private pointer
|
||||||
|
|||||||
@ -357,9 +357,11 @@
|
|||||||
(tr "dashboard.my-teams")]
|
(tr "dashboard.my-teams")]
|
||||||
(when (= default-team-id (:default-team-id organization))
|
(when (= default-team-id (:default-team-id organization))
|
||||||
tick-icon)]
|
tick-icon)]
|
||||||
[:hr {:role "separator" :class (stl/css :team-separator)}]
|
(when (seq organizations)
|
||||||
[:li {:role "presentation" :class (stl/css :org-section-label)}
|
[:*
|
||||||
(tr "dashboard.section.organizations")]
|
[:hr {:role "separator" :class (stl/css :team-separator)}]
|
||||||
|
[:li {:role "presentation" :class (stl/css :org-section-label)}
|
||||||
|
(tr "dashboard.section.organizations")]])
|
||||||
|
|
||||||
(for [org-item organizations]
|
(for [org-item organizations]
|
||||||
[:> dropdown-menu-item* {:on-click on-org-click
|
[:> dropdown-menu-item* {:on-click on-org-click
|
||||||
|
|||||||
@ -1,9 +1,19 @@
|
|||||||
(ns app.main.ui.flex-controls.common
|
(ns app.main.ui.flex-controls.common
|
||||||
(:require
|
(:require
|
||||||
[app.main.constants :as mconst]
|
[app.main.constants :as mconst]
|
||||||
|
[app.main.streams :as ms]
|
||||||
[app.main.ui.formats :as fmt]
|
[app.main.ui.formats :as fmt]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
;; ------------------------------------------------
|
||||||
|
;; INTERACTIVE TRANSFORM CLEANUP
|
||||||
|
;; ------------------------------------------------
|
||||||
|
|
||||||
|
;; Flex spacing controls (padding/margin/gap) call this from their
|
||||||
|
;; unmount cleanup, guarded on the resizing flag. See
|
||||||
|
;; `ms/clear-transform-preview!` for the rationale.
|
||||||
|
(def clear-transform-preview! ms/clear-transform-preview!)
|
||||||
|
|
||||||
;; ------------------------------------------------
|
;; ------------------------------------------------
|
||||||
;; CONSTANTS
|
;; CONSTANTS
|
||||||
;; ------------------------------------------------
|
;; ------------------------------------------------
|
||||||
|
|||||||
@ -98,6 +98,11 @@
|
|||||||
(when on-change
|
(when on-change
|
||||||
(on-change modifiers)))))))]
|
(on-change modifiers)))))))]
|
||||||
|
|
||||||
|
(mf/with-effect []
|
||||||
|
(fn []
|
||||||
|
(when (some? @resizing)
|
||||||
|
(fcc/clear-transform-preview!))))
|
||||||
|
|
||||||
[:g.gap-rect
|
[:g.gap-rect
|
||||||
[:rect.info-area
|
[:rect.info-area
|
||||||
{:x (:x rect-data)
|
{:x (:x rect-data)
|
||||||
|
|||||||
@ -105,6 +105,11 @@
|
|||||||
(when on-change
|
(when on-change
|
||||||
(on-change modifiers)))))))]
|
(on-change modifiers)))))))]
|
||||||
|
|
||||||
|
(mf/with-effect []
|
||||||
|
(fn []
|
||||||
|
(when @resizing?
|
||||||
|
(fcc/clear-transform-preview!))))
|
||||||
|
|
||||||
[:rect.margin-rect
|
[:rect.margin-rect
|
||||||
{:x (:x rect-data)
|
{:x (:x rect-data)
|
||||||
:y (:y rect-data)
|
:y (:y rect-data)
|
||||||
|
|||||||
@ -105,6 +105,11 @@
|
|||||||
(when on-change
|
(when on-change
|
||||||
(on-change modifiers)))))))]
|
(on-change modifiers)))))))]
|
||||||
|
|
||||||
|
(mf/with-effect []
|
||||||
|
(fn []
|
||||||
|
(when @resizing?
|
||||||
|
(fcc/clear-transform-preview!))))
|
||||||
|
|
||||||
[:g.padding-rect
|
[:g.padding-rect
|
||||||
[:rect.info-area
|
[:rect.info-area
|
||||||
{:x (:x rect-data)
|
{:x (:x rect-data)
|
||||||
|
|||||||
@ -12,8 +12,8 @@
|
|||||||
"clean": "rm -rf dist/"
|
"clean": "rm -rf dist/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@penpot/plugin-styles": "1.4.2",
|
"@penpot/plugin-styles": "1.5.0",
|
||||||
"@penpot/plugin-types": "1.4.2"
|
"@penpot/plugin-types": "1.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^10.1.0",
|
"cross-env": "^10.1.0",
|
||||||
|
|||||||
@ -214,8 +214,6 @@ export class PenpotUtils {
|
|||||||
public static getBounds(shape: Shape): Bounds {
|
public static getBounds(shape: Shape): Bounds {
|
||||||
if (shape.type === "text") {
|
if (shape.type === "text") {
|
||||||
const text = shape as Text;
|
const text = shape as Text;
|
||||||
// TODO: Remove ts-ignore once type definitions are updated
|
|
||||||
// @ts-ignore
|
|
||||||
return text.textBounds;
|
return text.textBounds;
|
||||||
} else {
|
} else {
|
||||||
return shape.bounds;
|
return shape.bounds;
|
||||||
@ -473,7 +471,6 @@ export class PenpotUtils {
|
|||||||
*/
|
*/
|
||||||
public static findTokensByName(name: string): any[] {
|
public static findTokensByName(name: string): any[] {
|
||||||
const tokens: any[] = [];
|
const tokens: any[] = [];
|
||||||
// @ts-ignore
|
|
||||||
const tokenCatalog = penpot.library.local.tokens;
|
const tokenCatalog = penpot.library.local.tokens;
|
||||||
|
|
||||||
for (const set of tokenCatalog.sets) {
|
for (const set of tokenCatalog.sets) {
|
||||||
@ -494,7 +491,6 @@ export class PenpotUtils {
|
|||||||
* @returns The first matching token, or null if not found
|
* @returns The first matching token, or null if not found
|
||||||
*/
|
*/
|
||||||
public static findTokenByName(name: string): any | null {
|
public static findTokenByName(name: string): any | null {
|
||||||
// @ts-ignore
|
|
||||||
const tokenCatalog = penpot.library.local.tokens;
|
const tokenCatalog = penpot.library.local.tokens;
|
||||||
|
|
||||||
for (const set of tokenCatalog.sets) {
|
for (const set of tokenCatalog.sets) {
|
||||||
@ -515,7 +511,6 @@ export class PenpotUtils {
|
|||||||
* @returns The TokenSet containing this token, or null if not found
|
* @returns The TokenSet containing this token, or null if not found
|
||||||
*/
|
*/
|
||||||
public static getTokenSet(token: any): any | null {
|
public static getTokenSet(token: any): any | null {
|
||||||
// @ts-ignore
|
|
||||||
const tokenCatalog = penpot.library.local.tokens;
|
const tokenCatalog = penpot.library.local.tokens;
|
||||||
|
|
||||||
for (const set of tokenCatalog.sets) {
|
for (const set of tokenCatalog.sets) {
|
||||||
@ -571,7 +566,6 @@ export class PenpotUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 1. Create the variant container
|
// 1. Create the variant container
|
||||||
// @ts-ignore — createVariantFromComponents was added after plugin-types@1.4.1
|
|
||||||
const container: VariantContainer = (penpot as any).createVariantFromComponents(components.map((c) => c.shape));
|
const container: VariantContainer = (penpot as any).createVariantFromComponents(components.map((c) => c.shape));
|
||||||
const variants = container.variants;
|
const variants = container.variants;
|
||||||
if (!variants) {
|
if (!variants) {
|
||||||
@ -617,7 +611,6 @@ export class PenpotUtils {
|
|||||||
*/
|
*/
|
||||||
public static tokenOverview(): Record<string, Record<string, string[]>> {
|
public static tokenOverview(): Record<string, Record<string, string[]>> {
|
||||||
const overview: Record<string, Record<string, string[]>> = {};
|
const overview: Record<string, Record<string, string[]>> = {};
|
||||||
// @ts-ignore
|
|
||||||
const tokenCatalog = penpot.library.local.tokens;
|
const tokenCatalog = penpot.library.local.tokens;
|
||||||
|
|
||||||
for (const set of tokenCatalog.sets) {
|
for (const set of tokenCatalog.sets) {
|
||||||
|
|||||||
@ -38,8 +38,6 @@ export class Task<TParams = any> {
|
|||||||
|
|
||||||
// Send to main.ts which will forward to MCP server via WebSocket
|
// Send to main.ts which will forward to MCP server via WebSocket
|
||||||
try {
|
try {
|
||||||
// TODO: Remove ts-ignore once Penpot types have been updated
|
|
||||||
// @ts-ignore
|
|
||||||
penpot.ui.sendMessage(response, true);
|
penpot.ui.sendMessage(response, true);
|
||||||
} catch (sendError) {
|
} catch (sendError) {
|
||||||
console.error("Failed to transfer task response for transmission to MCP server", sendError);
|
console.error("Failed to transfer task response for transmission to MCP server", sendError);
|
||||||
|
|||||||
9
mcp/packages/plugin/src/index.d.ts
vendored
9
mcp/packages/plugin/src/index.d.ts
vendored
@ -1,12 +1,3 @@
|
|||||||
import "@penpot/plugin-types";
|
|
||||||
|
|
||||||
declare module "@penpot/plugin-types" {
|
|
||||||
interface Penpot {
|
|
||||||
/** The Penpot application version string. */
|
|
||||||
version: string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface McpOptions {
|
interface McpOptions {
|
||||||
getToken(): string;
|
getToken(): string;
|
||||||
getServerUrl(): string;
|
getServerUrl(): string;
|
||||||
|
|||||||
@ -196,20 +196,13 @@ export class ExecuteCodeTaskHandler extends TaskHandler<ExecuteCodeTaskParams> {
|
|||||||
const code = task.params.code;
|
const code = task.params.code;
|
||||||
|
|
||||||
// set the flags naturalChildOrdering and throwValidationErrors to true during code execution.
|
// set the flags naturalChildOrdering and throwValidationErrors to true during code execution.
|
||||||
// TODO: Remove all ts-ignore once Penpot types have been updated
|
|
||||||
let originalNaturalChildOrdering: any, originalThrowValidationErrors: any;
|
let originalNaturalChildOrdering: any, originalThrowValidationErrors: any;
|
||||||
// @ts-ignore
|
|
||||||
if (penpot.flags) {
|
if (penpot.flags) {
|
||||||
// @ts-ignore
|
|
||||||
originalNaturalChildOrdering = penpot.flags.naturalChildOrdering;
|
originalNaturalChildOrdering = penpot.flags.naturalChildOrdering;
|
||||||
// @ts-ignore
|
|
||||||
penpot.flags.naturalChildOrdering = true;
|
penpot.flags.naturalChildOrdering = true;
|
||||||
// @ts-ignore
|
|
||||||
originalThrowValidationErrors = penpot.flags.throwValidationErrors;
|
originalThrowValidationErrors = penpot.flags.throwValidationErrors;
|
||||||
// @ts-ignore
|
|
||||||
penpot.flags.throwValidationErrors = true;
|
penpot.flags.throwValidationErrors = true;
|
||||||
} else {
|
} else {
|
||||||
// TODO: This can be removed once `flags` has been merged to PROD
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"You are using a version of the Penpot MCP server which is incompatible " +
|
"You are using a version of the Penpot MCP server which is incompatible " +
|
||||||
"with the connected Penpot version. " +
|
"with the connected Penpot version. " +
|
||||||
@ -228,9 +221,7 @@ export class ExecuteCodeTaskHandler extends TaskHandler<ExecuteCodeTaskParams> {
|
|||||||
})(context);
|
})(context);
|
||||||
} finally {
|
} finally {
|
||||||
// restore the original value of the flags
|
// restore the original value of the flags
|
||||||
// @ts-ignore
|
|
||||||
penpot.flags.naturalChildOrdering = originalNaturalChildOrdering;
|
penpot.flags.naturalChildOrdering = originalNaturalChildOrdering;
|
||||||
// @ts-ignore
|
|
||||||
penpot.flags.throwValidationErrors = originalThrowValidationErrors;
|
penpot.flags.throwValidationErrors = originalThrowValidationErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
20
mcp/pnpm-lock.yaml
generated
20
mcp/pnpm-lock.yaml
generated
@ -24,11 +24,11 @@ importers:
|
|||||||
packages/plugin:
|
packages/plugin:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@penpot/plugin-styles':
|
'@penpot/plugin-styles':
|
||||||
specifier: 1.4.2
|
specifier: 1.5.0
|
||||||
version: 1.4.2
|
version: 1.5.0
|
||||||
'@penpot/plugin-types':
|
'@penpot/plugin-types':
|
||||||
specifier: 1.4.2
|
specifier: 1.5.0
|
||||||
version: 1.4.2
|
version: 1.5.0
|
||||||
devDependencies:
|
devDependencies:
|
||||||
cross-env:
|
cross-env:
|
||||||
specifier: ^10.1.0
|
specifier: ^10.1.0
|
||||||
@ -496,11 +496,11 @@ packages:
|
|||||||
'@oxc-project/types@0.137.0':
|
'@oxc-project/types@0.137.0':
|
||||||
resolution: {integrity: sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA==}
|
resolution: {integrity: sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA==}
|
||||||
|
|
||||||
'@penpot/plugin-styles@1.4.2':
|
'@penpot/plugin-styles@1.5.0':
|
||||||
resolution: {integrity: sha512-/Rn6xy80W+mxAi6j5/SOiNY8P0qHMB1WW+j+nyZajecFSnVGPzSWOiMcIDH+Jtsz7Xpmd5AICpgVM0xjechQig==}
|
resolution: {integrity: sha512-rwXFBRPd0IZs3ens+eRT8oA5WqkQgF6xlW6fCfH7U1NHRjej9HH7vTGXmfjoIVml6Xx1sbyYHZVxkQC8Ub8+zA==}
|
||||||
|
|
||||||
'@penpot/plugin-types@1.4.2':
|
'@penpot/plugin-types@1.5.0':
|
||||||
resolution: {integrity: sha512-O8wU6RSYE8bIVU7g8cSTYi32ppxs3R13dq7X3Nn9tmDaJjBOKOBpVLuoRPIp3fJC65fv8/7om0sdrtFoL5v19g==}
|
resolution: {integrity: sha512-hFk4Rx66rLaSUWoN6bhxXkDI2ymwKg9xokdslvZvXM5MSmEmfhsJKUMwtuzgYWljbbfaQhK+DjK8g8yVbbavtA==}
|
||||||
|
|
||||||
'@pinojs/redact@0.4.0':
|
'@pinojs/redact@0.4.0':
|
||||||
resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==}
|
resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==}
|
||||||
@ -1762,9 +1762,9 @@ snapshots:
|
|||||||
|
|
||||||
'@oxc-project/types@0.137.0': {}
|
'@oxc-project/types@0.137.0': {}
|
||||||
|
|
||||||
'@penpot/plugin-styles@1.4.2': {}
|
'@penpot/plugin-styles@1.5.0': {}
|
||||||
|
|
||||||
'@penpot/plugin-types@1.4.2': {}
|
'@penpot/plugin-types@1.5.0': {}
|
||||||
|
|
||||||
'@pinojs/redact@0.4.0': {}
|
'@pinojs/redact@0.4.0': {}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user