diff --git a/mcp/packages/plugin/src/PenpotUtils.test.ts b/mcp/packages/plugin/src/PenpotUtils.test.ts index 845de06b51..62dcb60a80 100644 --- a/mcp/packages/plugin/src/PenpotUtils.test.ts +++ b/mcp/packages/plugin/src/PenpotUtils.test.ts @@ -50,14 +50,14 @@ function makeMockPenpot(variantComps: ReturnType[]) // Tests // --------------------------------------------------------------------------- -test("createVariant — single property: renames Property 1 and sets values", () => { +test("createVariantContainer — single property: renames Property 1 and sets values", () => { const calls: string[] = []; const comps = [makeVariantComponent(calls), makeVariantComponent(calls), makeVariantComponent(calls)]; const { mock, variants } = makeMockPenpot(comps); (globalThis as any).penpot = mock; - PenpotUtils.createVariant([ + PenpotUtils.createVariantContainer([ { shape: {} as any, properties: { Size: "Small" } }, { shape: {} as any, properties: { Size: "Medium" } }, { shape: {} as any, properties: { Size: "Large" } }, @@ -75,14 +75,14 @@ test("createVariant — single property: renames Property 1 and sets values", () ]); }); -test("createVariant — two properties: renames first, adds and renames second, sets all values", () => { +test("createVariantContainer — two properties: renames first, adds and renames second, sets all values", () => { const calls: string[] = []; const comps = [makeVariantComponent(calls), makeVariantComponent(calls)]; const { mock, variants } = makeMockPenpot(comps); (globalThis as any).penpot = mock; - PenpotUtils.createVariant([ + PenpotUtils.createVariantContainer([ { shape: {} as any, properties: { Size: "Small", State: "Default" } }, { shape: {} as any, properties: { Size: "Large", State: "Hover" } }, ]); @@ -100,7 +100,7 @@ test("createVariant — two properties: renames first, adds and renames second, ]); }); -test("createVariant — property name order follows first-seen order across components", () => { +test("createVariantContainer — property name order follows first-seen order across components", () => { const calls: string[] = []; const comps = [makeVariantComponent(calls), makeVariantComponent(calls)]; const { mock, variants } = makeMockPenpot(comps); @@ -108,7 +108,7 @@ test("createVariant — property name order follows first-seen order across comp (globalThis as any).penpot = mock; // "Color" appears first in comp[0]; "Size" appears first in comp[0] too - PenpotUtils.createVariant([ + PenpotUtils.createVariantContainer([ { shape: {} as any, properties: { Color: "Red", Size: "Small" } }, { shape: {} as any, properties: { Color: "Blue", Size: "Large" } }, ]); @@ -122,11 +122,11 @@ test("createVariant — property name order follows first-seen order across comp ]); }); -test("createVariant — returns the container from createVariantFromComponents", () => { +test("createVariantContainer — returns the container from createVariantFromComponents", () => { const { mock, container } = makeMockPenpot([]); (globalThis as any).penpot = mock; - const result = PenpotUtils.createVariant([{ shape: {} as any, properties: { X: "1" } }]); + const result = PenpotUtils.createVariantContainer([{ shape: {} as any, properties: { X: "1" } }]); assert.equal(result, container); }); diff --git a/mcp/packages/plugin/src/PenpotUtils.ts b/mcp/packages/plugin/src/PenpotUtils.ts index f9a8cba245..ae012608ac 100644 --- a/mcp/packages/plugin/src/PenpotUtils.ts +++ b/mcp/packages/plugin/src/PenpotUtils.ts @@ -539,8 +539,9 @@ export class PenpotUtils { * * @example * // Three button variants differing in Size + * // Given three main components s, m, l (here: the first three main components on the page) * const [s, m, l] = penpot.currentPage.findAllShapes(sh => sh.isMainComponent()).slice(0, 3) as Board[]; - * const container = PenpotUtils.createVariant([ + * const container = PenpotUtils.createVariantContainer([ * { shape: s, properties: { Size: 'Small' } }, * { shape: m, properties: { Size: 'Medium' } }, * { shape: l, properties: { Size: 'Large' } }, @@ -548,13 +549,13 @@ export class PenpotUtils { * * @example * // Two properties: Size × State - * const container = PenpotUtils.createVariant([ + * const container = PenpotUtils.createVariantContainer([ * { shape: s, properties: { Size: 'Small', State: 'Default' } }, * { shape: m, properties: { Size: 'Medium', State: 'Default' } }, * { shape: l, properties: { Size: 'Large', State: 'Hover' } }, * ]); */ - public static createVariant( + public static createVariantContainer( components: Array<{ shape: Board; properties: Record }> ): VariantContainer { // Collect all unique property names (preserving first-seen order) @@ -569,7 +570,12 @@ export class PenpotUtils { // @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) return container; + if (!variants) { + throw new Error( + "createVariantContainer: the created container has no `variants`. " + + "Ensure every provided shape is a main component instance (Board)." + ); + } // 2. Rename / add properties // createVariantFromComponents always creates exactly one property ("Property 1") diff --git a/mcp/packages/server/data/initial_instructions.md b/mcp/packages/server/data/initial_instructions.md index 69b2c07114..d11f7cdf95 100644 --- a/mcp/packages/server/data/initial_instructions.md +++ b/mcp/packages/server/data/initial_instructions.md @@ -305,17 +305,18 @@ Properties are often addressed positionally: `pos` parameter in various methods **Creating a variant group**: -Use `penpotUtils.createVariant(components)` — it handles the full multi-step workflow in one call: +Use `penpotUtils.createVariantContainer(components)` — it handles the full multi-step workflow in one call: ```js +// Given three main components s, m, l (here: the first three main components on the page) const [s, m, l] = penpot.currentPage.findAllShapes(sh => sh.isMainComponent()).slice(0, 3); // Single property: -const container = penpotUtils.createVariant([ +const container = penpotUtils.createVariantContainer([ { shape: s, properties: { Size: 'Small' } }, { shape: m, properties: { Size: 'Medium' } }, { shape: l, properties: { Size: 'Large' } }, ]); // Multiple properties: -const container2 = penpotUtils.createVariant([ +const container2 = penpotUtils.createVariantContainer([ { shape: s, properties: { Size: 'Small', State: 'Default' } }, { shape: m, properties: { Size: 'Medium', State: 'Default' } }, { shape: l, properties: { Size: 'Large', State: 'Hover' } }, @@ -323,7 +324,7 @@ const container2 = penpotUtils.createVariant([ ``` If you must use the lower-level API, follow this exact order — skipping or reordering steps leaves the variant broken: -1. `penpot.createVariantFromComponents(mainInstances)` — groups components; always creates one property called `"Property 1"`. +1. `penpot.createVariantFromComponents(mainInstances: Board[]): VariantContainer` — combines several main component instances into a new variant group. All components end up inside a single new container on the canvas; always creates one property called `"Property 1"`. 2. `container.variants.renameProperty(0, name)` — rename `Property 1`. 3. For each extra property: `variants.addProperty()` then `variants.renameProperty(pos, name)`. 4. For every component × every property: iterate `variants.variantComponents()` and call `comp.setVariantProperty(pos, value)`.