diff --git a/frontend/src/app/main/data/workspace/grid_layout/editor.cljs b/frontend/src/app/main/data/workspace/grid_layout/editor.cljs index 07fb2c093b..8546b1178a 100644 --- a/frontend/src/app/main/data/workspace/grid_layout/editor.cljs +++ b/frontend/src/app/main/data/workspace/grid_layout/editor.cljs @@ -11,6 +11,7 @@ [app.common.types.shape.layout :as ctl] [app.main.data.helpers :as dsh] [app.main.data.workspace.viewport-wasm :as dwvw] + [app.main.streams :as ms] [potok.v2.core :as ptk])) (defn hover-grid-cell @@ -88,7 +89,11 @@ (ptk/reify ::stop-grid-layout-editing ptk/UpdateEvent (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 [grid-id] diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 48cf42d014..d0e612b493 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -143,8 +143,7 @@ ptk/EffectEvent (effect [_ _ _] - (rx/push! ms/wasm-modifiers nil) - (rx/push! ms/workspace-selrect nil)))) + (ms/clear-transform-preview!)))) ;; -- Resize -------------------------------------------------------- diff --git a/frontend/src/app/main/streams.cljs b/frontend/src/app/main/streams.cljs index 1fe8e55d9b..a2fce0a4e6 100644 --- a/frontend/src/app/main/streams.cljs +++ b/frontend/src/app/main/streams.cljs @@ -32,6 +32,17 @@ (defonce workspace-selrect (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 (defonce ^:private pointer diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs index 5acdc06b84..34df0c491a 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs @@ -357,9 +357,11 @@ (tr "dashboard.my-teams")] (when (= default-team-id (:default-team-id organization)) tick-icon)] - [:hr {:role "separator" :class (stl/css :team-separator)}] - [:li {:role "presentation" :class (stl/css :org-section-label)} - (tr "dashboard.section.organizations")] + (when (seq 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] [:> dropdown-menu-item* {:on-click on-org-click diff --git a/frontend/src/app/main/ui/flex_controls/common.cljs b/frontend/src/app/main/ui/flex_controls/common.cljs index 1aa28a5289..72bed0cf0f 100644 --- a/frontend/src/app/main/ui/flex_controls/common.cljs +++ b/frontend/src/app/main/ui/flex_controls/common.cljs @@ -1,9 +1,19 @@ (ns app.main.ui.flex-controls.common (:require [app.main.constants :as mconst] + [app.main.streams :as ms] [app.main.ui.formats :as fmt] [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 ;; ------------------------------------------------ diff --git a/frontend/src/app/main/ui/flex_controls/gap.cljs b/frontend/src/app/main/ui/flex_controls/gap.cljs index 38926c9887..6bcb237821 100644 --- a/frontend/src/app/main/ui/flex_controls/gap.cljs +++ b/frontend/src/app/main/ui/flex_controls/gap.cljs @@ -98,6 +98,11 @@ (when on-change (on-change modifiers)))))))] + (mf/with-effect [] + (fn [] + (when (some? @resizing) + (fcc/clear-transform-preview!)))) + [:g.gap-rect [:rect.info-area {:x (:x rect-data) diff --git a/frontend/src/app/main/ui/flex_controls/margin.cljs b/frontend/src/app/main/ui/flex_controls/margin.cljs index d8ad044355..b8d39c73fb 100644 --- a/frontend/src/app/main/ui/flex_controls/margin.cljs +++ b/frontend/src/app/main/ui/flex_controls/margin.cljs @@ -105,6 +105,11 @@ (when on-change (on-change modifiers)))))))] + (mf/with-effect [] + (fn [] + (when @resizing? + (fcc/clear-transform-preview!)))) + [:rect.margin-rect {:x (:x rect-data) :y (:y rect-data) diff --git a/frontend/src/app/main/ui/flex_controls/padding.cljs b/frontend/src/app/main/ui/flex_controls/padding.cljs index c10f83cd31..1b125717bd 100644 --- a/frontend/src/app/main/ui/flex_controls/padding.cljs +++ b/frontend/src/app/main/ui/flex_controls/padding.cljs @@ -105,6 +105,11 @@ (when on-change (on-change modifiers)))))))] + (mf/with-effect [] + (fn [] + (when @resizing? + (fcc/clear-transform-preview!)))) + [:g.padding-rect [:rect.info-area {:x (:x rect-data) diff --git a/mcp/packages/plugin/package.json b/mcp/packages/plugin/package.json index a14df52313..6852dff522 100644 --- a/mcp/packages/plugin/package.json +++ b/mcp/packages/plugin/package.json @@ -12,8 +12,8 @@ "clean": "rm -rf dist/" }, "dependencies": { - "@penpot/plugin-styles": "1.4.2", - "@penpot/plugin-types": "1.4.2" + "@penpot/plugin-styles": "1.5.0", + "@penpot/plugin-types": "1.5.0" }, "devDependencies": { "cross-env": "^10.1.0", diff --git a/mcp/packages/plugin/src/PenpotUtils.ts b/mcp/packages/plugin/src/PenpotUtils.ts index e5f4d525f0..f856f14cc4 100644 --- a/mcp/packages/plugin/src/PenpotUtils.ts +++ b/mcp/packages/plugin/src/PenpotUtils.ts @@ -214,8 +214,6 @@ export class PenpotUtils { public static getBounds(shape: Shape): Bounds { if (shape.type === "text") { const text = shape as Text; - // TODO: Remove ts-ignore once type definitions are updated - // @ts-ignore return text.textBounds; } else { return shape.bounds; @@ -473,7 +471,6 @@ export class PenpotUtils { */ public static findTokensByName(name: string): any[] { const tokens: any[] = []; - // @ts-ignore const tokenCatalog = penpot.library.local.tokens; for (const set of tokenCatalog.sets) { @@ -494,7 +491,6 @@ export class PenpotUtils { * @returns The first matching token, or null if not found */ public static findTokenByName(name: string): any | null { - // @ts-ignore const tokenCatalog = penpot.library.local.tokens; for (const set of tokenCatalog.sets) { @@ -515,7 +511,6 @@ export class PenpotUtils { * @returns The TokenSet containing this token, or null if not found */ public static getTokenSet(token: any): any | null { - // @ts-ignore const tokenCatalog = penpot.library.local.tokens; for (const set of tokenCatalog.sets) { @@ -571,7 +566,6 @@ export class PenpotUtils { } // 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 variants = container.variants; if (!variants) { @@ -617,7 +611,6 @@ export class PenpotUtils { */ public static tokenOverview(): Record> { const overview: Record> = {}; - // @ts-ignore const tokenCatalog = penpot.library.local.tokens; for (const set of tokenCatalog.sets) { diff --git a/mcp/packages/plugin/src/TaskHandler.ts b/mcp/packages/plugin/src/TaskHandler.ts index a8f05a4229..7bc0aa3085 100644 --- a/mcp/packages/plugin/src/TaskHandler.ts +++ b/mcp/packages/plugin/src/TaskHandler.ts @@ -38,8 +38,6 @@ export class Task { // Send to main.ts which will forward to MCP server via WebSocket try { - // TODO: Remove ts-ignore once Penpot types have been updated - // @ts-ignore penpot.ui.sendMessage(response, true); } catch (sendError) { console.error("Failed to transfer task response for transmission to MCP server", sendError); diff --git a/mcp/packages/plugin/src/index.d.ts b/mcp/packages/plugin/src/index.d.ts index 42587c8304..a0eda651e1 100644 --- a/mcp/packages/plugin/src/index.d.ts +++ b/mcp/packages/plugin/src/index.d.ts @@ -1,12 +1,3 @@ -import "@penpot/plugin-types"; - -declare module "@penpot/plugin-types" { - interface Penpot { - /** The Penpot application version string. */ - version: string; - } -} - interface McpOptions { getToken(): string; getServerUrl(): string; diff --git a/mcp/packages/plugin/src/task-handlers/ExecuteCodeTaskHandler.ts b/mcp/packages/plugin/src/task-handlers/ExecuteCodeTaskHandler.ts index b464c599ef..df2fb65832 100644 --- a/mcp/packages/plugin/src/task-handlers/ExecuteCodeTaskHandler.ts +++ b/mcp/packages/plugin/src/task-handlers/ExecuteCodeTaskHandler.ts @@ -196,20 +196,13 @@ export class ExecuteCodeTaskHandler extends TaskHandler { const code = task.params.code; // 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; - // @ts-ignore if (penpot.flags) { - // @ts-ignore originalNaturalChildOrdering = penpot.flags.naturalChildOrdering; - // @ts-ignore penpot.flags.naturalChildOrdering = true; - // @ts-ignore originalThrowValidationErrors = penpot.flags.throwValidationErrors; - // @ts-ignore penpot.flags.throwValidationErrors = true; } else { - // TODO: This can be removed once `flags` has been merged to PROD throw new Error( "You are using a version of the Penpot MCP server which is incompatible " + "with the connected Penpot version. " + @@ -228,9 +221,7 @@ export class ExecuteCodeTaskHandler extends TaskHandler { })(context); } finally { // restore the original value of the flags - // @ts-ignore penpot.flags.naturalChildOrdering = originalNaturalChildOrdering; - // @ts-ignore penpot.flags.throwValidationErrors = originalThrowValidationErrors; } diff --git a/mcp/pnpm-lock.yaml b/mcp/pnpm-lock.yaml index f81ed1183d..dec172251d 100644 --- a/mcp/pnpm-lock.yaml +++ b/mcp/pnpm-lock.yaml @@ -24,11 +24,11 @@ importers: packages/plugin: dependencies: '@penpot/plugin-styles': - specifier: 1.4.2 - version: 1.4.2 + specifier: 1.5.0 + version: 1.5.0 '@penpot/plugin-types': - specifier: 1.4.2 - version: 1.4.2 + specifier: 1.5.0 + version: 1.5.0 devDependencies: cross-env: specifier: ^10.1.0 @@ -496,11 +496,11 @@ packages: '@oxc-project/types@0.137.0': resolution: {integrity: sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA==} - '@penpot/plugin-styles@1.4.2': - resolution: {integrity: sha512-/Rn6xy80W+mxAi6j5/SOiNY8P0qHMB1WW+j+nyZajecFSnVGPzSWOiMcIDH+Jtsz7Xpmd5AICpgVM0xjechQig==} + '@penpot/plugin-styles@1.5.0': + resolution: {integrity: sha512-rwXFBRPd0IZs3ens+eRT8oA5WqkQgF6xlW6fCfH7U1NHRjej9HH7vTGXmfjoIVml6Xx1sbyYHZVxkQC8Ub8+zA==} - '@penpot/plugin-types@1.4.2': - resolution: {integrity: sha512-O8wU6RSYE8bIVU7g8cSTYi32ppxs3R13dq7X3Nn9tmDaJjBOKOBpVLuoRPIp3fJC65fv8/7om0sdrtFoL5v19g==} + '@penpot/plugin-types@1.5.0': + resolution: {integrity: sha512-hFk4Rx66rLaSUWoN6bhxXkDI2ymwKg9xokdslvZvXM5MSmEmfhsJKUMwtuzgYWljbbfaQhK+DjK8g8yVbbavtA==} '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} @@ -1762,9 +1762,9 @@ snapshots: '@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': {}